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, const char *queryString)
 
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 12526 of file tablecmds.c.

References add_exact_object_address(), Assert, CatalogTupleUpdate(), 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, and HeapTupleData::t_self.

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

12530 {
12531  HeapTuple classTup;
12532  Form_pg_class classForm;
12533  ObjectAddress thisobj;
12534  bool already_done = false;
12535 
12536  classTup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relOid));
12537  if (!HeapTupleIsValid(classTup))
12538  elog(ERROR, "cache lookup failed for relation %u", relOid);
12539  classForm = (Form_pg_class) GETSTRUCT(classTup);
12540 
12541  Assert(classForm->relnamespace == oldNspOid);
12542 
12543  thisobj.classId = RelationRelationId;
12544  thisobj.objectId = relOid;
12545  thisobj.objectSubId = 0;
12546 
12547  /*
12548  * If the object has already been moved, don't move it again. If it's
12549  * already in the right place, don't move it, but still fire the object
12550  * access hook.
12551  */
12552  already_done = object_address_present(&thisobj, objsMoved);
12553  if (!already_done && oldNspOid != newNspOid)
12554  {
12555  /* check for duplicate name (more friendly than unique-index failure) */
12556  if (get_relname_relid(NameStr(classForm->relname),
12557  newNspOid) != InvalidOid)
12558  ereport(ERROR,
12559  (errcode(ERRCODE_DUPLICATE_TABLE),
12560  errmsg("relation \"%s\" already exists in schema \"%s\"",
12561  NameStr(classForm->relname),
12562  get_namespace_name(newNspOid))));
12563 
12564  /* classTup is a copy, so OK to scribble on */
12565  classForm->relnamespace = newNspOid;
12566 
12567  CatalogTupleUpdate(classRel, &classTup->t_self, classTup);
12568 
12569  /* Update dependency on schema if caller said so */
12570  if (hasDependEntry &&
12572  relOid,
12574  oldNspOid,
12575  newNspOid) != 1)
12576  elog(ERROR, "failed to change schema dependency for relation \"%s\"",
12577  NameStr(classForm->relname));
12578  }
12579  if (!already_done)
12580  {
12581  add_exact_object_address(&thisobj, objsMoved);
12582 
12584  }
12585 
12586  heap_freetuple(classTup);
12587 }
#define NamespaceRelationId
Definition: pg_namespace.h:34
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define RelationRelationId
Definition: pg_class.h:29
bool object_address_present(const ObjectAddress *object, const ObjectAddresses *addrs)
Definition: dependency.c:2167
int errcode(int sqlerrcode)
Definition: elog.c:575
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2107
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1372
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#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:1683
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3033
#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:675
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:165
int errmsg(const char *fmt,...)
Definition: elog.c:797
long changeDependencyFor(Oid classId, Oid objectId, Oid refClassId, Oid oldRefObjectId, Oid newRefObjectId)
Definition: pg_depend.c:295
#define NameStr(name)
Definition: c.h:499
#define elog
Definition: elog.h:219
void AlterTable ( Oid  relid,
LOCKMODE  lockmode,
AlterTableStmt stmt 
)

Definition at line 3089 of file tablecmds.c.

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

Referenced by ProcessUtilitySlow().

3090 {
3091  Relation rel;
3092 
3093  /* Caller is required to provide an adequate lock. */
3094  rel = relation_open(relid, NoLock);
3095 
3096  CheckTableNotInUse(rel, "ALTER TABLE");
3097 
3098  ATController(stmt, rel, stmt->cmds, stmt->relation->inh, lockmode);
3099 }
static void ATController(AlterTableStmt *parsetree, Relation rel, List *cmds, bool recurse, LOCKMODE lockmode)
Definition: tablecmds.c:3406
#define NoLock
Definition: lockdefs.h:34
void CheckTableNotInUse(Relation rel, const char *stmt)
Definition: tablecmds.c:3010
bool inh
Definition: primnodes.h:69
RangeVar * relation
Definition: parsenodes.h:1677
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1114
LOCKMODE AlterTableGetLockLevel ( List cmds)

Definition at line 3158 of file tablecmds.c.

References AccessExclusiveLock, AlterTableGetRelOptionsLockLevel(), AT_AddColumn, AT_AddColumnToView, AT_AddConstraint, AT_AddConstraintRecurse, AT_AddIdentity, AT_AddIndex, AT_AddIndexConstraint, AT_AddInherit, AT_AddOf, AT_AddOids, AT_AlterColumnGenericOptions, AT_AlterColumnType, AT_AlterConstraint, AT_AttachPartition, AT_ChangeOwner, AT_ClusterOn, AT_ColumnDefault, AT_DetachPartition, AT_DisableRowSecurity, AT_DisableRule, AT_DisableTrig, AT_DisableTrigAll, AT_DisableTrigUser, AT_DropCluster, AT_DropColumn, AT_DropConstraint, AT_DropIdentity, 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_SetIdentity, 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().

3159 {
3160  /*
3161  * This only works if we read catalog tables using MVCC snapshots.
3162  */
3163  ListCell *lcmd;
3165 
3166  foreach(lcmd, cmds)
3167  {
3168  AlterTableCmd *cmd = (AlterTableCmd *) lfirst(lcmd);
3169  LOCKMODE cmd_lockmode = AccessExclusiveLock; /* default for compiler */
3170 
3171  switch (cmd->subtype)
3172  {
3173  /*
3174  * These subcommands rewrite the heap, so require full locks.
3175  */
3176  case AT_AddColumn: /* may rewrite heap, in some cases and visible
3177  * to SELECT */
3178  case AT_SetTableSpace: /* must rewrite heap */
3179  case AT_AlterColumnType: /* must rewrite heap */
3180  case AT_AddOids: /* must rewrite heap */
3181  cmd_lockmode = AccessExclusiveLock;
3182  break;
3183 
3184  /*
3185  * These subcommands may require addition of toast tables. If
3186  * we add a toast table to a table currently being scanned, we
3187  * might miss data added to the new toast table by concurrent
3188  * insert transactions.
3189  */
3190  case AT_SetStorage: /* may add toast tables, see
3191  * ATRewriteCatalogs() */
3192  cmd_lockmode = AccessExclusiveLock;
3193  break;
3194 
3195  /*
3196  * Removing constraints can affect SELECTs that have been
3197  * optimised assuming the constraint holds true.
3198  */
3199  case AT_DropConstraint: /* as DROP INDEX */
3200  case AT_DropNotNull: /* may change some SQL plans */
3201  cmd_lockmode = AccessExclusiveLock;
3202  break;
3203 
3204  /*
3205  * Subcommands that may be visible to concurrent SELECTs
3206  */
3207  case AT_DropColumn: /* change visible to SELECT */
3208  case AT_AddColumnToView: /* CREATE VIEW */
3209  case AT_DropOids: /* calls AT_DropColumn */
3210  case AT_EnableAlwaysRule: /* may change SELECT rules */
3211  case AT_EnableReplicaRule: /* may change SELECT rules */
3212  case AT_EnableRule: /* may change SELECT rules */
3213  case AT_DisableRule: /* may change SELECT rules */
3214  cmd_lockmode = AccessExclusiveLock;
3215  break;
3216 
3217  /*
3218  * Changing owner may remove implicit SELECT privileges
3219  */
3220  case AT_ChangeOwner: /* change visible to SELECT */
3221  cmd_lockmode = AccessExclusiveLock;
3222  break;
3223 
3224  /*
3225  * Changing foreign table options may affect optimization.
3226  */
3227  case AT_GenericOptions:
3229  cmd_lockmode = AccessExclusiveLock;
3230  break;
3231 
3232  /*
3233  * These subcommands affect write operations only.
3234  */
3235  case AT_EnableTrig:
3236  case AT_EnableAlwaysTrig:
3237  case AT_EnableReplicaTrig:
3238  case AT_EnableTrigAll:
3239  case AT_EnableTrigUser:
3240  case AT_DisableTrig:
3241  case AT_DisableTrigAll:
3242  case AT_DisableTrigUser:
3243  cmd_lockmode = ShareRowExclusiveLock;
3244  break;
3245 
3246  /*
3247  * These subcommands affect write operations only. XXX
3248  * Theoretically, these could be ShareRowExclusiveLock.
3249  */
3250  case AT_ColumnDefault:
3251  case AT_AlterConstraint:
3252  case AT_AddIndex: /* from ADD CONSTRAINT */
3253  case AT_AddIndexConstraint:
3254  case AT_ReplicaIdentity:
3255  case AT_SetNotNull:
3256  case AT_EnableRowSecurity:
3257  case AT_DisableRowSecurity:
3258  case AT_ForceRowSecurity:
3259  case AT_NoForceRowSecurity:
3260  case AT_AddIdentity:
3261  case AT_DropIdentity:
3262  case AT_SetIdentity:
3263  cmd_lockmode = AccessExclusiveLock;
3264  break;
3265 
3266  case AT_AddConstraint:
3267  case AT_ProcessedConstraint: /* becomes AT_AddConstraint */
3268  case AT_AddConstraintRecurse: /* becomes AT_AddConstraint */
3269  case AT_ReAddConstraint: /* becomes AT_AddConstraint */
3270  if (IsA(cmd->def, Constraint))
3271  {
3272  Constraint *con = (Constraint *) cmd->def;
3273 
3274  switch (con->contype)
3275  {
3276  case CONSTR_EXCLUSION:
3277  case CONSTR_PRIMARY:
3278  case CONSTR_UNIQUE:
3279 
3280  /*
3281  * Cases essentially the same as CREATE INDEX. We
3282  * could reduce the lock strength to ShareLock if
3283  * we can work out how to allow concurrent catalog
3284  * updates. XXX Might be set down to
3285  * ShareRowExclusiveLock but requires further
3286  * analysis.
3287  */
3288  cmd_lockmode = AccessExclusiveLock;
3289  break;
3290  case CONSTR_FOREIGN:
3291 
3292  /*
3293  * We add triggers to both tables when we add a
3294  * Foreign Key, so the lock level must be at least
3295  * as strong as CREATE TRIGGER.
3296  */
3297  cmd_lockmode = ShareRowExclusiveLock;
3298  break;
3299 
3300  default:
3301  cmd_lockmode = AccessExclusiveLock;
3302  }
3303  }
3304  break;
3305 
3306  /*
3307  * These subcommands affect inheritance behaviour. Queries
3308  * started before us will continue to see the old inheritance
3309  * behaviour, while queries started after we commit will see
3310  * new behaviour. No need to prevent reads or writes to the
3311  * subtable while we hook it up though. Changing the TupDesc
3312  * may be a problem, so keep highest lock.
3313  */
3314  case AT_AddInherit:
3315  case AT_DropInherit:
3316  cmd_lockmode = AccessExclusiveLock;
3317  break;
3318 
3319  /*
3320  * These subcommands affect implicit row type conversion. They
3321  * have affects similar to CREATE/DROP CAST on queries. don't
3322  * provide for invalidating parse trees as a result of such
3323  * changes, so we keep these at AccessExclusiveLock.
3324  */
3325  case AT_AddOf:
3326  case AT_DropOf:
3327  cmd_lockmode = AccessExclusiveLock;
3328  break;
3329 
3330  /*
3331  * Only used by CREATE OR REPLACE VIEW which must conflict
3332  * with an SELECTs currently using the view.
3333  */
3334  case AT_ReplaceRelOptions:
3335  cmd_lockmode = AccessExclusiveLock;
3336  break;
3337 
3338  /*
3339  * These subcommands affect general strategies for performance
3340  * and maintenance, though don't change the semantic results
3341  * from normal data reads and writes. Delaying an ALTER TABLE
3342  * behind currently active writes only delays the point where
3343  * the new strategy begins to take effect, so there is no
3344  * benefit in waiting. In this case the minimum restriction
3345  * applies: we don't currently allow concurrent catalog
3346  * updates.
3347  */
3348  case AT_SetStatistics: /* Uses MVCC in getTableAttrs() */
3349  case AT_ClusterOn: /* Uses MVCC in getIndexes() */
3350  case AT_DropCluster: /* Uses MVCC in getIndexes() */
3351  case AT_SetOptions: /* Uses MVCC in getTableAttrs() */
3352  case AT_ResetOptions: /* Uses MVCC in getTableAttrs() */
3353  cmd_lockmode = ShareUpdateExclusiveLock;
3354  break;
3355 
3356  case AT_SetLogged:
3357  case AT_SetUnLogged:
3358  cmd_lockmode = AccessExclusiveLock;
3359  break;
3360 
3361  case AT_ValidateConstraint: /* Uses MVCC in getConstraints() */
3362  cmd_lockmode = ShareUpdateExclusiveLock;
3363  break;
3364 
3365  /*
3366  * Rel options are more complex than first appears. Options
3367  * are set here for tables, views and indexes; for historical
3368  * reasons these can all be used with ALTER TABLE, so we can't
3369  * decide between them using the basic grammar.
3370  */
3371  case AT_SetRelOptions: /* Uses MVCC in getIndexes() and
3372  * getTables() */
3373  case AT_ResetRelOptions: /* Uses MVCC in getIndexes() and
3374  * getTables() */
3375  cmd_lockmode = AlterTableGetRelOptionsLockLevel((List *) cmd->def);
3376  break;
3377 
3378  case AT_AttachPartition:
3379  case AT_DetachPartition:
3380  cmd_lockmode = AccessExclusiveLock;
3381  break;
3382 
3383  default: /* oops */
3384  elog(ERROR, "unrecognized alter table type: %d",
3385  (int) cmd->subtype);
3386  break;
3387  }
3388 
3389  /*
3390  * Take the greatest lockmode from any subcommand
3391  */
3392  if (cmd_lockmode > lockmode)
3393  lockmode = cmd_lockmode;
3394  }
3395 
3396  return lockmode;
3397 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
int LOCKMODE
Definition: lockdefs.h:26
AlterTableType subtype
Definition: parsenodes.h:1764
#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:1528
#define AccessExclusiveLock
Definition: lockdefs.h:45
ConstrType contype
Definition: parsenodes.h:2065
#define elog
Definition: elog.h:219
Definition: pg_list.h:45
void AlterTableInternal ( Oid  relid,
List cmds,
bool  recurse 
)

Definition at line 3113 of file tablecmds.c.

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

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

3114 {
3115  Relation rel;
3116  LOCKMODE lockmode = AlterTableGetLockLevel(cmds);
3117 
3118  rel = relation_open(relid, lockmode);
3119 
3121 
3122  ATController(NULL, rel, cmds, recurse, lockmode);
3123 }
int LOCKMODE
Definition: lockdefs.h:26
static void ATController(AlterTableStmt *parsetree, Relation rel, List *cmds, bool recurse, LOCKMODE lockmode)
Definition: tablecmds.c:3406
LOCKMODE AlterTableGetLockLevel(List *cmds)
Definition: tablecmds.c:3158
#define NULL
Definition: c.h:229
void EventTriggerAlterTableRelid(Oid objectId)
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1114
Oid AlterTableLookupRelation ( AlterTableStmt stmt,
LOCKMODE  lockmode 
)

Definition at line 3039 of file tablecmds.c.

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

Referenced by ProcessUtilitySlow().

3040 {
3041  return RangeVarGetRelidExtended(stmt->relation, lockmode, stmt->missing_ok, false,
3043  (void *) stmt);
3044 }
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, bool missing_ok, bool nowait, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:218
static void RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg)
Definition: tablecmds.c:13003
RangeVar * relation
Definition: parsenodes.h:1677
Oid AlterTableMoveAll ( AlterTableMoveAllStmt stmt)

Definition at line 10621 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_PARTITIONED_TABLE, RELKIND_RELATION, AlterTableMoveAllStmt::roles, roleSpecsToIds(), ScanKeyInit(), and AlterTableCmd::subtype.

Referenced by ProcessUtilitySlow().

10622 {
10623  List *relations = NIL;
10624  ListCell *l;
10625  ScanKeyData key[1];
10626  Relation rel;
10627  HeapScanDesc scan;
10628  HeapTuple tuple;
10629  Oid orig_tablespaceoid;
10630  Oid new_tablespaceoid;
10631  List *role_oids = roleSpecsToIds(stmt->roles);
10632 
10633  /* Ensure we were not asked to move something we can't */
10634  if (stmt->objtype != OBJECT_TABLE && stmt->objtype != OBJECT_INDEX &&
10635  stmt->objtype != OBJECT_MATVIEW)
10636  ereport(ERROR,
10637  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
10638  errmsg("only tables, indexes, and materialized views exist in tablespaces")));
10639 
10640  /* Get the orig and new tablespace OIDs */
10641  orig_tablespaceoid = get_tablespace_oid(stmt->orig_tablespacename, false);
10642  new_tablespaceoid = get_tablespace_oid(stmt->new_tablespacename, false);
10643 
10644  /* Can't move shared relations in to or out of pg_global */
10645  /* This is also checked by ATExecSetTableSpace, but nice to stop earlier */
10646  if (orig_tablespaceoid == GLOBALTABLESPACE_OID ||
10647  new_tablespaceoid == GLOBALTABLESPACE_OID)
10648  ereport(ERROR,
10649  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
10650  errmsg("cannot move relations in to or out of pg_global tablespace")));
10651 
10652  /*
10653  * Must have CREATE rights on the new tablespace, unless it is the
10654  * database default tablespace (which all users implicitly have CREATE
10655  * rights on).
10656  */
10657  if (OidIsValid(new_tablespaceoid) && new_tablespaceoid != MyDatabaseTableSpace)
10658  {
10659  AclResult aclresult;
10660 
10661  aclresult = pg_tablespace_aclcheck(new_tablespaceoid, GetUserId(),
10662  ACL_CREATE);
10663  if (aclresult != ACLCHECK_OK)
10665  get_tablespace_name(new_tablespaceoid));
10666  }
10667 
10668  /*
10669  * Now that the checks are done, check if we should set either to
10670  * InvalidOid because it is our database's default tablespace.
10671  */
10672  if (orig_tablespaceoid == MyDatabaseTableSpace)
10673  orig_tablespaceoid = InvalidOid;
10674 
10675  if (new_tablespaceoid == MyDatabaseTableSpace)
10676  new_tablespaceoid = InvalidOid;
10677 
10678  /* no-op */
10679  if (orig_tablespaceoid == new_tablespaceoid)
10680  return new_tablespaceoid;
10681 
10682  /*
10683  * Walk the list of objects in the tablespace and move them. This will
10684  * only find objects in our database, of course.
10685  */
10686  ScanKeyInit(&key[0],
10688  BTEqualStrategyNumber, F_OIDEQ,
10689  ObjectIdGetDatum(orig_tablespaceoid));
10690 
10692  scan = heap_beginscan_catalog(rel, 1, key);
10693  while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
10694  {
10695  Oid relOid = HeapTupleGetOid(tuple);
10696  Form_pg_class relForm;
10697 
10698  relForm = (Form_pg_class) GETSTRUCT(tuple);
10699 
10700  /*
10701  * Do not move objects in pg_catalog as part of this, if an admin
10702  * really wishes to do so, they can issue the individual ALTER
10703  * commands directly.
10704  *
10705  * Also, explicitly avoid any shared tables, temp tables, or TOAST
10706  * (TOAST will be moved with the main table).
10707  */
10708  if (IsSystemNamespace(relForm->relnamespace) || relForm->relisshared ||
10709  isAnyTempNamespace(relForm->relnamespace) ||
10710  relForm->relnamespace == PG_TOAST_NAMESPACE)
10711  continue;
10712 
10713  /* Only move the object type requested */
10714  if ((stmt->objtype == OBJECT_TABLE &&
10715  relForm->relkind != RELKIND_RELATION &&
10716  relForm->relkind != RELKIND_PARTITIONED_TABLE) ||
10717  (stmt->objtype == OBJECT_INDEX &&
10718  relForm->relkind != RELKIND_INDEX) ||
10719  (stmt->objtype == OBJECT_MATVIEW &&
10720  relForm->relkind != RELKIND_MATVIEW))
10721  continue;
10722 
10723  /* Check if we are only moving objects owned by certain roles */
10724  if (role_oids != NIL && !list_member_oid(role_oids, relForm->relowner))
10725  continue;
10726 
10727  /*
10728  * Handle permissions-checking here since we are locking the tables
10729  * and also to avoid doing a bunch of work only to fail part-way. Note
10730  * that permissions will also be checked by AlterTableInternal().
10731  *
10732  * Caller must be considered an owner on the table to move it.
10733  */
10734  if (!pg_class_ownercheck(relOid, GetUserId()))
10736  NameStr(relForm->relname));
10737 
10738  if (stmt->nowait &&
10740  ereport(ERROR,
10741  (errcode(ERRCODE_OBJECT_IN_USE),
10742  errmsg("aborting because lock on relation \"%s.%s\" is not available",
10743  get_namespace_name(relForm->relnamespace),
10744  NameStr(relForm->relname))));
10745  else
10747 
10748  /* Add to our list of objects to move */
10749  relations = lappend_oid(relations, relOid);
10750  }
10751 
10752  heap_endscan(scan);
10754 
10755  if (relations == NIL)
10756  ereport(NOTICE,
10757  (errcode(ERRCODE_NO_DATA_FOUND),
10758  errmsg("no matching relations in tablespace \"%s\" found",
10759  orig_tablespaceoid == InvalidOid ? "(database default)" :
10760  get_tablespace_name(orig_tablespaceoid))));
10761 
10762  /* Everything is locked, loop through and move all of the relations. */
10763  foreach(l, relations)
10764  {
10765  List *cmds = NIL;
10767 
10768  cmd->subtype = AT_SetTableSpace;
10769  cmd->name = stmt->new_tablespacename;
10770 
10771  cmds = lappend(cmds, cmd);
10772 
10774  /* OID is set by AlterTableInternal */
10775  AlterTableInternal(lfirst_oid(l), cmds, false);
10777  }
10778 
10779  return new_tablespaceoid;
10780 }
#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:1380
AclResult pg_tablespace_aclcheck(Oid spc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4496
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
void heap_endscan(HeapScanDesc scan)
Definition: heapam.c:1578
Oid GetUserId(void)
Definition: miscinit.c:283
#define RelationRelationId
Definition: pg_class.h:29
#define Anum_pg_class_reltablespace
Definition: pg_class.h:110
#define RELKIND_MATVIEW
Definition: pg_class.h:165
#define AccessShareLock
Definition: lockdefs.h:36
#define GLOBALTABLESPACE_OID
Definition: pg_tablespace.h:64
Definition: nodes.h:509
int errcode(int sqlerrcode)
Definition: elog.c:575
AlterTableType subtype
Definition: parsenodes.h:1764
#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:538
Oid MyDatabaseTableSpace
Definition: globals.c:79
void EventTriggerAlterTableStart(Node *parsetree)
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define ACL_CREATE
Definition: parsenodes.h:82
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3033
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3399
HeapScanDesc heap_beginscan_catalog(Relation relation, int nkeys, ScanKey key)
Definition: heapam.c:1399
#define ereport(elevel, rest)
Definition: elog.h:122
List * lappend(List *list, void *datum)
Definition: list.c:128
#define RELKIND_PARTITIONED_TABLE
Definition: pg_class.h:168
AclResult
Definition: acl.h:170
HeapTuple heap_getnext(HeapScanDesc scan, ScanDirection direction)
Definition: heapam.c:1794
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
bool IsSystemNamespace(Oid namespaceId)
Definition: catalog.c:163
#define InvalidOid
Definition: postgres_ext.h:36
#define NOTICE
Definition: elog.h:37
#define makeNode(_type_)
Definition: nodes.h:557
List * roleSpecsToIds(List *memberNames)
Definition: user.c:1361
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:505
#define NULL
Definition: c.h:229
bool pg_class_ownercheck(Oid class_oid, Oid roleid)
Definition: aclchk.c:4546
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
void AlterTableInternal(Oid relid, List *cmds, bool recurse)
Definition: tablecmds.c:3113
#define AccessExclusiveLock
Definition: lockdefs.h:45
int errmsg(const char *fmt,...)
Definition: elog.c:797
char * get_tablespace_name(Oid spc_oid)
Definition: tablespace.c:1426
#define NameStr(name)
Definition: c.h:499
#define RELKIND_INDEX
Definition: pg_class.h:161
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
bool isAnyTempNamespace(Oid namespaceId)
Definition: namespace.c:3156
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:105
#define RELKIND_RELATION
Definition: pg_class.h:160
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 12417 of file tablecmds.c.

References AccessExclusiveLock, AlterTableNamespaceInternal(), CheckSetNamespace(), DEPENDENCY_AUTO, DEPENDENCY_INTERNAL, 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().

12418 {
12419  Relation rel;
12420  Oid relid;
12421  Oid oldNspOid;
12422  Oid nspOid;
12423  RangeVar *newrv;
12424  ObjectAddresses *objsMoved;
12425  ObjectAddress myself;
12426 
12428  stmt->missing_ok, false,
12430  (void *) stmt);
12431 
12432  if (!OidIsValid(relid))
12433  {
12434  ereport(NOTICE,
12435  (errmsg("relation \"%s\" does not exist, skipping",
12436  stmt->relation->relname)));
12437  return InvalidObjectAddress;
12438  }
12439 
12440  rel = relation_open(relid, NoLock);
12441 
12442  oldNspOid = RelationGetNamespace(rel);
12443 
12444  /* If it's an owned sequence, disallow moving it by itself. */
12445  if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
12446  {
12447  Oid tableId;
12448  int32 colId;
12449 
12450  if (sequenceIsOwned(relid, DEPENDENCY_AUTO, &tableId, &colId) ||
12451  sequenceIsOwned(relid, DEPENDENCY_INTERNAL, &tableId, &colId))
12452  ereport(ERROR,
12453  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
12454  errmsg("cannot move an owned sequence into another schema"),
12455  errdetail("Sequence \"%s\" is linked to table \"%s\".",
12457  get_rel_name(tableId))));
12458  }
12459 
12460  /* Get and lock schema OID and check its permissions. */
12461  newrv = makeRangeVar(stmt->newschema, RelationGetRelationName(rel), -1);
12463 
12464  /* common checks on switching namespaces */
12465  CheckSetNamespace(oldNspOid, nspOid);
12466 
12467  objsMoved = new_object_addresses();
12468  AlterTableNamespaceInternal(rel, oldNspOid, nspOid, objsMoved);
12469  free_object_addresses(objsMoved);
12470 
12471  ObjectAddressSet(myself, RelationRelationId, relid);
12472 
12473  if (oldschema)
12474  *oldschema = oldNspOid;
12475 
12476  /* close rel, but keep lock until commit */
12477  relation_close(rel, NoLock);
12478 
12479  return myself;
12480 }
bool sequenceIsOwned(Oid seqId, char deptype, Oid *tableId, int32 *colId)
Definition: pg_depend.c:500
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, bool missing_ok, bool nowait, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:218
#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:1260
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2052
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2323
Form_pg_class rd_rel
Definition: rel.h:114
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:538
signed int int32
Definition: c.h:256
char * relname
Definition: primnodes.h:68
#define ERROR
Definition: elog.h:43
void AlterTableNamespaceInternal(Relation rel, Oid oldNspOid, Oid nspOid, ObjectAddresses *objsMoved)
Definition: tablecmds.c:12488
#define NoLock
Definition: lockdefs.h:34
static void RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg)
Definition: tablecmds.c:13003
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define RelationGetRelationName(relation)
Definition: rel.h:436
#define ereport(elevel, rest)
Definition: elog.h:122
void CheckSetNamespace(Oid oldNspOid, Oid nspOid)
Definition: namespace.c:2928
Oid RangeVarGetAndCheckCreationNamespace(RangeVar *relation, LOCKMODE lockmode, Oid *existing_relation_id)
Definition: namespace.c:508
#define NOTICE
Definition: elog.h:37
#define NULL
Definition: c.h:229
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define AccessExclusiveLock
Definition: lockdefs.h:45
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:797
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1114
#define RELKIND_SEQUENCE
Definition: pg_class.h:162
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1726
RangeVar * makeRangeVar(char *schemaname, char *relname, int location)
Definition: makefuncs.c:419
#define RelationGetNamespace(relation)
Definition: rel.h:443
void AlterTableNamespaceInternal ( Relation  rel,
Oid  oldNspOid,
Oid  nspOid,
ObjectAddresses objsMoved 
)

Definition at line 12488 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_PARTITIONED_TABLE, RELKIND_RELATION, and RowExclusiveLock.

Referenced by AlterObjectNamespace_oid(), and AlterTableNamespace().

12490 {
12491  Relation classRel;
12492 
12493  Assert(objsMoved != NULL);
12494 
12495  /* OK, modify the pg_class row and pg_depend entry */
12497 
12498  AlterRelationNamespaceInternal(classRel, RelationGetRelid(rel), oldNspOid,
12499  nspOid, true, objsMoved);
12500 
12501  /* Fix the table's row type too */
12502  AlterTypeNamespaceInternal(rel->rd_rel->reltype,
12503  nspOid, false, false, objsMoved);
12504 
12505  /* Fix other dependent stuff */
12506  if (rel->rd_rel->relkind == RELKIND_RELATION ||
12507  rel->rd_rel->relkind == RELKIND_MATVIEW ||
12508  rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
12509  {
12510  AlterIndexNamespaces(classRel, rel, oldNspOid, nspOid, objsMoved);
12511  AlterSeqNamespaces(classRel, rel, oldNspOid, nspOid,
12512  objsMoved, AccessExclusiveLock);
12513  AlterConstraintNamespaces(RelationGetRelid(rel), oldNspOid, nspOid,
12514  false, objsMoved);
12515  }
12516 
12517  heap_close(classRel, RowExclusiveLock);
12518 }
#define RelationRelationId
Definition: pg_class.h:29
#define RELKIND_MATVIEW
Definition: pg_class.h:165
Oid AlterTypeNamespaceInternal(Oid typeOid, Oid nspOid, bool isImplicitArray, bool errorOnTableType, ObjectAddresses *objsMoved)
Definition: typecmds.c:3491
#define heap_close(r, l)
Definition: heapam.h:97
Form_pg_class rd_rel
Definition: rel.h:114
static void AlterIndexNamespaces(Relation classRel, Relation rel, Oid oldNspOid, Oid newNspOid, ObjectAddresses *objsMoved)
Definition: tablecmds.c:12596
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:12641
#define RowExclusiveLock
Definition: lockdefs.h:38
#define RELKIND_PARTITIONED_TABLE
Definition: pg_class.h:168
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
void AlterRelationNamespaceInternal(Relation classRel, Oid relOid, Oid oldNspOid, Oid newNspOid, bool hasDependEntry, ObjectAddresses *objsMoved)
Definition: tablecmds.c:12526
#define AccessExclusiveLock
Definition: lockdefs.h:45
#define RELKIND_RELATION
Definition: pg_class.h:160
#define RelationGetRelid(relation)
Definition: rel.h:416
void AtEOSubXact_on_commit_actions ( bool  isCommit,
SubTransactionId  mySubid,
SubTransactionId  parentSubid 
)

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

12895 {
12896  ListCell *cur_item;
12897  ListCell *prev_item;
12898 
12899  prev_item = NULL;
12900  cur_item = list_head(on_commits);
12901 
12902  while (cur_item != NULL)
12903  {
12904  OnCommitItem *oc = (OnCommitItem *) lfirst(cur_item);
12905 
12906  if (!isCommit && oc->creating_subid == mySubid)
12907  {
12908  /* cur_item must be removed */
12909  on_commits = list_delete_cell(on_commits, cur_item, prev_item);
12910  pfree(oc);
12911  if (prev_item)
12912  cur_item = lnext(prev_item);
12913  else
12914  cur_item = list_head(on_commits);
12915  }
12916  else
12917  {
12918  /* cur_item must be preserved */
12919  if (oc->creating_subid == mySubid)
12920  oc->creating_subid = parentSubid;
12921  if (oc->deleting_subid == mySubid)
12922  oc->deleting_subid = isCommit ? parentSubid : InvalidSubTransactionId;
12923  prev_item = cur_item;
12924  cur_item = lnext(prev_item);
12925  }
12926  }
12927 }
SubTransactionId creating_subid
Definition: tablecmds.c:120
void pfree(void *pointer)
Definition: mcxt.c:950
static List * on_commits
Definition: tablecmds.c:124
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:121
#define NULL
Definition: c.h:229
#define lfirst(lc)
Definition: pg_list.h:106
#define InvalidSubTransactionId
Definition: c.h:403
void AtEOXact_on_commit_actions ( bool  isCommit)

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

12852 {
12853  ListCell *cur_item;
12854  ListCell *prev_item;
12855 
12856  prev_item = NULL;
12857  cur_item = list_head(on_commits);
12858 
12859  while (cur_item != NULL)
12860  {
12861  OnCommitItem *oc = (OnCommitItem *) lfirst(cur_item);
12862 
12863  if (isCommit ? oc->deleting_subid != InvalidSubTransactionId :
12865  {
12866  /* cur_item must be removed */
12867  on_commits = list_delete_cell(on_commits, cur_item, prev_item);
12868  pfree(oc);
12869  if (prev_item)
12870  cur_item = lnext(prev_item);
12871  else
12872  cur_item = list_head(on_commits);
12873  }
12874  else
12875  {
12876  /* cur_item must be preserved */
12879  prev_item = cur_item;
12880  cur_item = lnext(prev_item);
12881  }
12882  }
12883 }
SubTransactionId creating_subid
Definition: tablecmds.c:120
void pfree(void *pointer)
Definition: mcxt.c:950
static List * on_commits
Definition: tablecmds.c:124
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:121
#define NULL
Definition: c.h:229
#define lfirst(lc)
Definition: pg_list.h:106
#define InvalidSubTransactionId
Definition: c.h:403
void ATExecChangeOwner ( Oid  relationOid,
Oid  newOwnerId,
bool  recursing,
LOCKMODE  lockmode 
)

Definition at line 9810 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(), CatalogTupleUpdate(), change_owner_fix_column_acls(), change_owner_recurse_to_sequences(), changeDependencyOnOwner(), check_is_member_of_role(), DatumGetAclP, DEPENDENCY_AUTO, DEPENDENCY_INTERNAL, 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_PARTITIONED_TABLE, RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_TOASTVALUE, RELKIND_VIEW, RELOID, RowExclusiveLock, SearchSysCache1, sequenceIsOwned(), superuser(), SysCacheGetAttr(), HeapTupleData::t_self, and WARNING.

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

9811 {
9812  Relation target_rel;
9813  Relation class_rel;
9814  HeapTuple tuple;
9815  Form_pg_class tuple_class;
9816 
9817  /*
9818  * Get exclusive lock till end of transaction on the target table. Use
9819  * relation_open so that we can work on indexes and sequences.
9820  */
9821  target_rel = relation_open(relationOid, lockmode);
9822 
9823  /* Get its pg_class tuple, too */
9825 
9826  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relationOid));
9827  if (!HeapTupleIsValid(tuple))
9828  elog(ERROR, "cache lookup failed for relation %u", relationOid);
9829  tuple_class = (Form_pg_class) GETSTRUCT(tuple);
9830 
9831  /* Can we change the ownership of this tuple? */
9832  switch (tuple_class->relkind)
9833  {
9834  case RELKIND_RELATION:
9835  case RELKIND_VIEW:
9836  case RELKIND_MATVIEW:
9837  case RELKIND_FOREIGN_TABLE:
9839  /* ok to change owner */
9840  break;
9841  case RELKIND_INDEX:
9842  if (!recursing)
9843  {
9844  /*
9845  * Because ALTER INDEX OWNER used to be allowed, and in fact
9846  * is generated by old versions of pg_dump, we give a warning
9847  * and do nothing rather than erroring out. Also, to avoid
9848  * unnecessary chatter while restoring those old dumps, say
9849  * nothing at all if the command would be a no-op anyway.
9850  */
9851  if (tuple_class->relowner != newOwnerId)
9852  ereport(WARNING,
9853  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
9854  errmsg("cannot change owner of index \"%s\"",
9855  NameStr(tuple_class->relname)),
9856  errhint("Change the ownership of the index's table, instead.")));
9857  /* quick hack to exit via the no-op path */
9858  newOwnerId = tuple_class->relowner;
9859  }
9860  break;
9861  case RELKIND_SEQUENCE:
9862  if (!recursing &&
9863  tuple_class->relowner != newOwnerId)
9864  {
9865  /* if it's an owned sequence, disallow changing it by itself */
9866  Oid tableId;
9867  int32 colId;
9868 
9869  if (sequenceIsOwned(relationOid, DEPENDENCY_AUTO, &tableId, &colId) ||
9870  sequenceIsOwned(relationOid, DEPENDENCY_INTERNAL, &tableId, &colId))
9871  ereport(ERROR,
9872  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
9873  errmsg("cannot change owner of sequence \"%s\"",
9874  NameStr(tuple_class->relname)),
9875  errdetail("Sequence \"%s\" is linked to table \"%s\".",
9876  NameStr(tuple_class->relname),
9877  get_rel_name(tableId))));
9878  }
9879  break;
9881  if (recursing)
9882  break;
9883  ereport(ERROR,
9884  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
9885  errmsg("\"%s\" is a composite type",
9886  NameStr(tuple_class->relname)),
9887  errhint("Use ALTER TYPE instead.")));
9888  break;
9889  case RELKIND_TOASTVALUE:
9890  if (recursing)
9891  break;
9892  /* FALL THRU */
9893  default:
9894  ereport(ERROR,
9895  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
9896  errmsg("\"%s\" is not a table, view, sequence, or foreign table",
9897  NameStr(tuple_class->relname))));
9898  }
9899 
9900  /*
9901  * If the new owner is the same as the existing owner, consider the
9902  * command to have succeeded. This is for dump restoration purposes.
9903  */
9904  if (tuple_class->relowner != newOwnerId)
9905  {
9906  Datum repl_val[Natts_pg_class];
9907  bool repl_null[Natts_pg_class];
9908  bool repl_repl[Natts_pg_class];
9909  Acl *newAcl;
9910  Datum aclDatum;
9911  bool isNull;
9912  HeapTuple newtuple;
9913 
9914  /* skip permission checks when recursing to index or toast table */
9915  if (!recursing)
9916  {
9917  /* Superusers can always do it */
9918  if (!superuser())
9919  {
9920  Oid namespaceOid = tuple_class->relnamespace;
9921  AclResult aclresult;
9922 
9923  /* Otherwise, must be owner of the existing object */
9924  if (!pg_class_ownercheck(relationOid, GetUserId()))
9926  RelationGetRelationName(target_rel));
9927 
9928  /* Must be able to become new owner */
9929  check_is_member_of_role(GetUserId(), newOwnerId);
9930 
9931  /* New owner must have CREATE privilege on namespace */
9932  aclresult = pg_namespace_aclcheck(namespaceOid, newOwnerId,
9933  ACL_CREATE);
9934  if (aclresult != ACLCHECK_OK)
9936  get_namespace_name(namespaceOid));
9937  }
9938  }
9939 
9940  memset(repl_null, false, sizeof(repl_null));
9941  memset(repl_repl, false, sizeof(repl_repl));
9942 
9943  repl_repl[Anum_pg_class_relowner - 1] = true;
9944  repl_val[Anum_pg_class_relowner - 1] = ObjectIdGetDatum(newOwnerId);
9945 
9946  /*
9947  * Determine the modified ACL for the new owner. This is only
9948  * necessary when the ACL is non-null.
9949  */
9950  aclDatum = SysCacheGetAttr(RELOID, tuple,
9952  &isNull);
9953  if (!isNull)
9954  {
9955  newAcl = aclnewowner(DatumGetAclP(aclDatum),
9956  tuple_class->relowner, newOwnerId);
9957  repl_repl[Anum_pg_class_relacl - 1] = true;
9958  repl_val[Anum_pg_class_relacl - 1] = PointerGetDatum(newAcl);
9959  }
9960 
9961  newtuple = heap_modify_tuple(tuple, RelationGetDescr(class_rel), repl_val, repl_null, repl_repl);
9962 
9963  CatalogTupleUpdate(class_rel, &newtuple->t_self, newtuple);
9964 
9965  heap_freetuple(newtuple);
9966 
9967  /*
9968  * We must similarly update any per-column ACLs to reflect the new
9969  * owner; for neatness reasons that's split out as a subroutine.
9970  */
9971  change_owner_fix_column_acls(relationOid,
9972  tuple_class->relowner,
9973  newOwnerId);
9974 
9975  /*
9976  * Update owner dependency reference, if any. A composite type has
9977  * none, because it's tracked for the pg_type entry instead of here;
9978  * indexes and TOAST tables don't have their own entries either.
9979  */
9980  if (tuple_class->relkind != RELKIND_COMPOSITE_TYPE &&
9981  tuple_class->relkind != RELKIND_INDEX &&
9982  tuple_class->relkind != RELKIND_TOASTVALUE)
9984  newOwnerId);
9985 
9986  /*
9987  * Also change the ownership of the table's row type, if it has one
9988  */
9989  if (tuple_class->relkind != RELKIND_INDEX)
9990  AlterTypeOwnerInternal(tuple_class->reltype, newOwnerId);
9991 
9992  /*
9993  * If we are operating on a table or materialized view, also change
9994  * the ownership of any indexes and sequences that belong to the
9995  * relation, as well as its toast table (if it has one).
9996  */
9997  if (tuple_class->relkind == RELKIND_RELATION ||
9998  tuple_class->relkind == RELKIND_MATVIEW ||
9999  tuple_class->relkind == RELKIND_TOASTVALUE)
10000  {
10001  List *index_oid_list;
10002  ListCell *i;
10003 
10004  /* Find all the indexes belonging to this relation */
10005  index_oid_list = RelationGetIndexList(target_rel);
10006 
10007  /* For each index, recursively change its ownership */
10008  foreach(i, index_oid_list)
10009  ATExecChangeOwner(lfirst_oid(i), newOwnerId, true, lockmode);
10010 
10011  list_free(index_oid_list);
10012  }
10013 
10014  if (tuple_class->relkind == RELKIND_RELATION ||
10015  tuple_class->relkind == RELKIND_MATVIEW)
10016  {
10017  /* If it has a toast table, recurse to change its ownership */
10018  if (tuple_class->reltoastrelid != InvalidOid)
10019  ATExecChangeOwner(tuple_class->reltoastrelid, newOwnerId,
10020  true, lockmode);
10021 
10022  /* If it has dependent sequences, recurse to change them too */
10023  change_owner_recurse_to_sequences(relationOid, newOwnerId, lockmode);
10024  }
10025  }
10026 
10028 
10029  ReleaseSysCache(tuple);
10030  heap_close(class_rel, RowExclusiveLock);
10031  relation_close(target_rel, NoLock);
10032 }
#define Natts_pg_class
Definition: pg_class.h:102
int errhint(const char *fmt,...)
Definition: elog.c:987
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define Anum_pg_class_relacl
Definition: pg_class.h:133
bool sequenceIsOwned(Oid seqId, char deptype, Oid *tableId, int32 *colId)
Definition: pg_depend.c:500
#define RelationGetDescr(relation)
Definition: rel.h:428
Oid GetUserId(void)
Definition: miscinit.c:283
#define DatumGetAclP(X)
Definition: acl.h:113
#define PointerGetDatum(X)
Definition: postgres.h:562
#define RelationRelationId
Definition: pg_class.h:29
#define RELKIND_MATVIEW
Definition: pg_class.h:165
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:1260
void AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId)
Definition: typecmds.c:3361
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1372
unsigned int Oid
Definition: postgres_ext.h:31
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4484
#define RELKIND_COMPOSITE_TYPE
Definition: pg_class.h:166
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:156
signed int int32
Definition: c.h:256
void changeDependencyOnOwner(Oid classId, Oid objectId, Oid newOwnerId)
Definition: pg_shdepend.c:304
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define ACL_CREATE
Definition: parsenodes.h:82
ItemPointerData t_self
Definition: htup.h:65
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3033
#define NoLock
Definition: lockdefs.h:34
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3399
#define RowExclusiveLock
Definition: lockdefs.h:38
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define RelationGetRelationName(relation)
Definition: rel.h:436
#define RELKIND_FOREIGN_TABLE
Definition: pg_class.h:167
void check_is_member_of_role(Oid member, Oid role)
Definition: acl.c:4859
#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:9810
#define WARNING
Definition: elog.h:40
#define RELKIND_PARTITIONED_TABLE
Definition: pg_class.h:168
#define RELKIND_TOASTVALUE
Definition: pg_class.h:163
AclResult
Definition: acl.h:170
uintptr_t Datum
Definition: postgres.h:372
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1279
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
bool pg_class_ownercheck(Oid class_oid, Oid roleid)
Definition: aclchk.c:4546
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
static void change_owner_recurse_to_sequences(Oid relationOid, Oid newOwnerId, LOCKMODE lockmode)
Definition: tablecmds.c:10106
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4345
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
static void change_owner_fix_column_acls(Oid relationOid, Oid oldOwnerId, Oid newOwnerId)
Definition: tablecmds.c:10041
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define RELKIND_VIEW
Definition: pg_class.h:164
void list_free(List *list)
Definition: list.c:1133
int i
#define NameStr(name)
Definition: c.h:499
#define RELKIND_INDEX
Definition: pg_class.h:161
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1114
#define elog
Definition: elog.h:219
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:160
#define RELKIND_SEQUENCE
Definition: pg_class.h:162
Definition: pg_list.h:45
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1726
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:107
void check_of_type ( HeapTuple  typetuple)

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

5020 {
5021  Form_pg_type typ = (Form_pg_type) GETSTRUCT(typetuple);
5022  bool typeOk = false;
5023 
5024  if (typ->typtype == TYPTYPE_COMPOSITE)
5025  {
5026  Relation typeRelation;
5027 
5028  Assert(OidIsValid(typ->typrelid));
5029  typeRelation = relation_open(typ->typrelid, AccessShareLock);
5030  typeOk = (typeRelation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE);
5031 
5032  /*
5033  * Close the parent rel, but keep our AccessShareLock on it until xact
5034  * commit. That will prevent someone else from deleting or ALTERing
5035  * the type before the typed table creation/conversion commits.
5036  */
5037  relation_close(typeRelation, NoLock);
5038  }
5039  if (!typeOk)
5040  ereport(ERROR,
5041  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
5042  errmsg("type %s is not a composite type",
5043  format_type_be(HeapTupleGetOid(typetuple)))));
5044 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define TYPTYPE_COMPOSITE
Definition: pg_type.h:721
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:575
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1260
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:114
#define OidIsValid(objectId)
Definition: c.h:538
#define RELKIND_COMPOSITE_TYPE
Definition: pg_class.h:166
#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:675
int errmsg(const char *fmt,...)
Definition: elog.c:797
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1114
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
void CheckTableNotInUse ( Relation  rel,
const char *  stmt 
)

Definition at line 3010 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(), ATPrepAlterColumnType(), ATSimpleRecursion(), ATTypedTableRecursion(), cluster_rel(), DefineIndex(), DefineVirtualRelation(), ExecRefreshMatView(), heap_drop_with_catalog(), index_drop(), reindex_index(), and truncate_check_rel().

3011 {
3012  int expected_refcnt;
3013 
3014  expected_refcnt = rel->rd_isnailed ? 2 : 1;
3015  if (rel->rd_refcnt != expected_refcnt)
3016  ereport(ERROR,
3017  (errcode(ERRCODE_OBJECT_IN_USE),
3018  /* translator: first %s is a SQL command, eg ALTER TABLE */
3019  errmsg("cannot %s \"%s\" because "
3020  "it is being used by active queries in this session",
3021  stmt, RelationGetRelationName(rel))));
3022 
3023  if (rel->rd_rel->relkind != RELKIND_INDEX &&
3025  ereport(ERROR,
3026  (errcode(ERRCODE_OBJECT_IN_USE),
3027  /* translator: first %s is a SQL command, eg ALTER TABLE */
3028  errmsg("cannot %s \"%s\" because "
3029  "it has pending trigger events",
3030  stmt, RelationGetRelationName(rel))));
3031 }
bool rd_isnailed
Definition: rel.h:91
int errcode(int sqlerrcode)
Definition: elog.c:575
Form_pg_class rd_rel
Definition: rel.h:114
#define ERROR
Definition: elog.h:43
#define RelationGetRelationName(relation)
Definition: rel.h:436
#define ereport(elevel, rest)
Definition: elog.h:122
bool AfterTriggerPendingOnRel(Oid relid)
Definition: trigger.c:5025
int errmsg(const char *fmt,...)
Definition: elog.c:797
int rd_refcnt
Definition: rel.h:88
#define RELKIND_INDEX
Definition: pg_class.h:161
#define RelationGetRelid(relation)
Definition: rel.h:416
ObjectAddress DefineRelation ( CreateStmt stmt,
char  relkind,
Oid  ownerId,
ObjectAddress typaddress,
const char *  queryString 
)

Definition at line 498 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(), check_new_partition_bound(), CommandCounterIncrement(), ComputePartitionAttrs(), CookedConstraint::conoid, CONSTR_DEFAULT, CreateStmt::constraints, CookedConstraint::contype, ColumnDef::cooked_default, elog, ereport, errcode(), errmsg(), ERROR, CookedConstraint::expr, get_tablespace_name(), get_tablespace_oid(), GetDefaultTablespace(), GetUserId(), GLOBALTABLESPACE_OID, heap_close, heap_create_with_catalog(), heap_open(), HEAP_RELOPT_NAMESPACES, heap_reloptions(), ColumnDef::identity, CookedConstraint::inhcount, CreateStmt::inhRelations, InSecurityRestrictedOperation(), interpretOidsOption(), InvalidOid, CookedConstraint::is_local, CookedConstraint::is_no_inherit, lappend(), lfirst, linitial_oid, list_concat(), list_length(), make_parsestate(), MergeAttributes(), MyDatabaseTableSpace, CookedConstraint::name, NAMEDATALEN, NIL, NoLock, NULL, ObjectAddressSet, CreateStmt::ofTypename, OidIsValid, CreateStmt::oncommit, ONCOMMIT_NOOP, CreateStmt::options, ParseState::p_sourcetext, palloc(), CreateStmt::partbound, PARTITION_MAX_KEYS, PartitionSpec::partParams, CreateStmt::partspec, pg_tablespace_aclcheck(), pg_type_aclcheck(), RangeVarGetAndCheckCreationNamespace(), RawColumnDefault::raw_default, ColumnDef::raw_default, RelationData::rd_rel, CreateStmt::relation, relation_close(), relation_open(), RelationGetRelationName, RelationRelationId, RELKIND_PARTITIONED_TABLE, RELKIND_RELATION, RELKIND_VIEW, RangeVar::relname, RangeVar::relpersistence, RELPERSISTENCE_TEMP, CookedConstraint::skip_validation, StoreCatalogInheritance(), StorePartitionBound(), StorePartitionKey(), StrNCpy, CreateStmt::tableElts, CreateStmt::tablespacename, tupleDesc::tdhasoid, transformPartitionBound(), transformPartitionSpec(), transformRelOptions(), typenameTypeId(), and view_reloptions().

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

500 {
501  char relname[NAMEDATALEN];
502  Oid namespaceId;
503  Oid relationId;
504  Oid tablespaceId;
505  Relation rel;
507  List *inheritOids;
508  List *old_constraints;
509  bool localHasOids;
510  int parentOidCount;
511  List *rawDefaults;
512  List *cookedDefaults;
513  Datum reloptions;
514  ListCell *listptr;
515  AttrNumber attnum;
516  static char *validnsps[] = HEAP_RELOPT_NAMESPACES;
517  Oid ofTypeId;
518  ObjectAddress address;
519 
520  /*
521  * Truncate relname to appropriate length (probably a waste of time, as
522  * parser should have done this already).
523  */
524  StrNCpy(relname, stmt->relation->relname, NAMEDATALEN);
525 
526  /*
527  * Check consistency of arguments
528  */
529  if (stmt->oncommit != ONCOMMIT_NOOP
531  ereport(ERROR,
532  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
533  errmsg("ON COMMIT can only be used on temporary tables")));
534 
535  if (stmt->partspec != NULL)
536  {
537  if (relkind != RELKIND_RELATION)
538  elog(ERROR, "unexpected relkind: %d", (int) relkind);
539 
540  relkind = RELKIND_PARTITIONED_TABLE;
541  }
542 
543  /*
544  * Look up the namespace in which we are supposed to create the relation,
545  * check we have permission to create there, lock it against concurrent
546  * drop, and mark stmt->relation as RELPERSISTENCE_TEMP if a temporary
547  * namespace is selected.
548  */
549  namespaceId =
551 
552  /*
553  * Security check: disallow creating temp tables from security-restricted
554  * code. This is needed because calling code might not expect untrusted
555  * tables to appear in pg_temp at the front of its search path.
556  */
559  ereport(ERROR,
560  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
561  errmsg("cannot create temporary table within security-restricted operation")));
562 
563  /*
564  * Select tablespace to use. If not specified, use default tablespace
565  * (which may in turn default to database's default).
566  */
567  if (stmt->tablespacename)
568  {
569  tablespaceId = get_tablespace_oid(stmt->tablespacename, false);
570  }
571  else
572  {
573  tablespaceId = GetDefaultTablespace(stmt->relation->relpersistence);
574  /* note InvalidOid is OK in this case */
575  }
576 
577  /* Check permissions except when using database's default */
578  if (OidIsValid(tablespaceId) && tablespaceId != MyDatabaseTableSpace)
579  {
580  AclResult aclresult;
581 
582  aclresult = pg_tablespace_aclcheck(tablespaceId, GetUserId(),
583  ACL_CREATE);
584  if (aclresult != ACLCHECK_OK)
586  get_tablespace_name(tablespaceId));
587  }
588 
589  /* In all cases disallow placing user relations in pg_global */
590  if (tablespaceId == GLOBALTABLESPACE_OID)
591  ereport(ERROR,
592  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
593  errmsg("only shared relations can be placed in pg_global tablespace")));
594 
595  /* Identify user ID that will own the table */
596  if (!OidIsValid(ownerId))
597  ownerId = GetUserId();
598 
599  /*
600  * Parse and validate reloptions, if any.
601  */
602  reloptions = transformRelOptions((Datum) 0, stmt->options, NULL, validnsps,
603  true, false);
604 
605  if (relkind == RELKIND_VIEW)
606  (void) view_reloptions(reloptions, true);
607  else
608  (void) heap_reloptions(relkind, reloptions, true);
609 
610  if (stmt->ofTypename)
611  {
612  AclResult aclresult;
613 
614  ofTypeId = typenameTypeId(NULL, stmt->ofTypename);
615 
616  aclresult = pg_type_aclcheck(ofTypeId, GetUserId(), ACL_USAGE);
617  if (aclresult != ACLCHECK_OK)
618  aclcheck_error_type(aclresult, ofTypeId);
619  }
620  else
621  ofTypeId = InvalidOid;
622 
623  /*
624  * Look up inheritance ancestors and generate relation schema, including
625  * inherited attributes. (Note that stmt->tableElts is destructively
626  * modified by MergeAttributes.)
627  */
628  stmt->tableElts =
630  stmt->relation->relpersistence,
631  stmt->partbound != NULL,
632  &inheritOids, &old_constraints, &parentOidCount);
633 
634  /*
635  * Create a tuple descriptor from the relation schema. Note that this
636  * deals with column names, types, and NOT NULL constraints, but not
637  * default values or CHECK constraints; we handle those below.
638  */
639  descriptor = BuildDescForRelation(stmt->tableElts);
640 
641  /*
642  * Notice that we allow OIDs here only for plain tables and partitioned
643  * tables, even though some other relkinds can support them. This is
644  * necessary because the default_with_oids GUC must apply only to plain
645  * tables and not any other relkind; doing otherwise would break existing
646  * pg_dump files. We could allow explicit "WITH OIDS" while not allowing
647  * default_with_oids to affect other relkinds, but it would complicate
648  * interpretOidsOption().
649  */
650  localHasOids = interpretOidsOption(stmt->options,
651  (relkind == RELKIND_RELATION ||
652  relkind == RELKIND_PARTITIONED_TABLE));
653  descriptor->tdhasoid = (localHasOids || parentOidCount > 0);
654 
655  /*
656  * If a partitioned table doesn't have the system OID column, then none of
657  * its partitions should have it.
658  */
659  if (stmt->partbound && parentOidCount == 0 && localHasOids)
660  ereport(ERROR,
661  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
662  errmsg("cannot create table with OIDs as partition of table without OIDs")));
663 
664  /*
665  * Find columns with default values and prepare for insertion of the
666  * defaults. Pre-cooked (that is, inherited) defaults go into a list of
667  * CookedConstraint structs that we'll pass to heap_create_with_catalog,
668  * while raw defaults go into a list of RawColumnDefault structs that will
669  * be processed by AddRelationNewConstraints. (We can't deal with raw
670  * expressions until we can do transformExpr.)
671  *
672  * We can set the atthasdef flags now in the tuple descriptor; this just
673  * saves StoreAttrDefault from having to do an immediate update of the
674  * pg_attribute rows.
675  */
676  rawDefaults = NIL;
677  cookedDefaults = NIL;
678  attnum = 0;
679 
680  foreach(listptr, stmt->tableElts)
681  {
682  ColumnDef *colDef = lfirst(listptr);
683 
684  attnum++;
685 
686  if (colDef->raw_default != NULL)
687  {
688  RawColumnDefault *rawEnt;
689 
690  Assert(colDef->cooked_default == NULL);
691 
692  rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault));
693  rawEnt->attnum = attnum;
694  rawEnt->raw_default = colDef->raw_default;
695  rawDefaults = lappend(rawDefaults, rawEnt);
696  descriptor->attrs[attnum - 1]->atthasdef = true;
697  }
698  else if (colDef->cooked_default != NULL)
699  {
700  CookedConstraint *cooked;
701 
702  cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
703  cooked->contype = CONSTR_DEFAULT;
704  cooked->conoid = InvalidOid; /* until created */
705  cooked->name = NULL;
706  cooked->attnum = attnum;
707  cooked->expr = colDef->cooked_default;
708  cooked->skip_validation = false;
709  cooked->is_local = true; /* not used for defaults */
710  cooked->inhcount = 0; /* ditto */
711  cooked->is_no_inherit = false;
712  cookedDefaults = lappend(cookedDefaults, cooked);
713  descriptor->attrs[attnum - 1]->atthasdef = true;
714  }
715 
716  if (colDef->identity)
717  descriptor->attrs[attnum - 1]->attidentity = colDef->identity;
718  }
719 
720  /*
721  * Create the relation. Inherited defaults and constraints are passed in
722  * for immediate handling --- since they don't need parsing, they can be
723  * stored immediately.
724  */
725  relationId = heap_create_with_catalog(relname,
726  namespaceId,
727  tablespaceId,
728  InvalidOid,
729  InvalidOid,
730  ofTypeId,
731  ownerId,
732  descriptor,
733  list_concat(cookedDefaults,
734  old_constraints),
735  relkind,
736  stmt->relation->relpersistence,
737  false,
738  false,
739  localHasOids,
740  parentOidCount,
741  stmt->oncommit,
742  reloptions,
743  true,
745  false,
746  typaddress);
747 
748  /* Store inheritance information for new rel. */
749  StoreCatalogInheritance(relationId, inheritOids, stmt->partbound != NULL);
750 
751  /*
752  * We must bump the command counter to make the newly-created relation
753  * tuple visible for opening.
754  */
756 
757  /*
758  * Open the new relation and acquire exclusive lock on it. This isn't
759  * really necessary for locking out other backends (since they can't see
760  * the new rel anyway until we commit), but it keeps the lock manager from
761  * complaining about deadlock risks.
762  */
763  rel = relation_open(relationId, AccessExclusiveLock);
764 
765  /* Process and store partition bound, if any. */
766  if (stmt->partbound)
767  {
768  PartitionBoundSpec *bound;
769  ParseState *pstate;
770  Oid parentId = linitial_oid(inheritOids);
771  Relation parent;
772 
773  /* Already have strong enough lock on the parent */
774  parent = heap_open(parentId, NoLock);
775 
776  /*
777  * We are going to try to validate the partition bound specification
778  * against the partition key of parentRel, so it better have one.
779  */
780  if (parent->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
781  ereport(ERROR,
782  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
783  errmsg("\"%s\" is not partitioned",
784  RelationGetRelationName(parent))));
785 
786  /* Tranform the bound values */
787  pstate = make_parsestate(NULL);
788  pstate->p_sourcetext = queryString;
789 
790  bound = transformPartitionBound(pstate, parent, stmt->partbound);
791 
792  /*
793  * Check first that the new partition's bound is valid and does not
794  * overlap with any of existing partitions of the parent - note that
795  * it does not return on error.
796  */
797  check_new_partition_bound(relname, parent, bound);
798 
799  /* Update the pg_class entry. */
800  StorePartitionBound(rel, parent, bound);
801 
802  heap_close(parent, NoLock);
803 
804  /*
805  * The code that follows may also update the pg_class tuple to update
806  * relnumchecks, so bump up the command counter to avoid the "already
807  * updated by self" error.
808  */
810  }
811 
812  /*
813  * Process the partitioning specification (if any) and store the partition
814  * key information into the catalog.
815  */
816  if (stmt->partspec)
817  {
818  char strategy;
819  int partnatts;
820  AttrNumber partattrs[PARTITION_MAX_KEYS];
821  Oid partopclass[PARTITION_MAX_KEYS];
822  Oid partcollation[PARTITION_MAX_KEYS];
823  List *partexprs = NIL;
824 
825  partnatts = list_length(stmt->partspec->partParams);
826 
827  /* Protect fixed-size arrays here and in executor */
828  if (partnatts > PARTITION_MAX_KEYS)
829  ereport(ERROR,
830  (errcode(ERRCODE_TOO_MANY_COLUMNS),
831  errmsg("cannot partition using more than %d columns",
833 
834  /*
835  * We need to transform the raw parsetrees corresponding to partition
836  * expressions into executable expression trees. Like column defaults
837  * and CHECK constraints, we could not have done the transformation
838  * earlier.
839  */
840  stmt->partspec = transformPartitionSpec(rel, stmt->partspec,
841  &strategy);
842 
844  partattrs, &partexprs, partopclass,
845  partcollation);
846 
847  StorePartitionKey(rel, strategy, partnatts, partattrs, partexprs,
848  partopclass, partcollation);
849  }
850 
851  /*
852  * Now add any newly specified column default values and CHECK constraints
853  * to the new relation. These are passed to us in the form of raw
854  * parsetrees; we need to transform them to executable expression trees
855  * before they can be added. The most convenient way to do that is to
856  * apply the parser's transformExpr routine, but transformExpr doesn't
857  * work unless we have a pre-existing relation. So, the transformation has
858  * to be postponed to this final step of CREATE TABLE.
859  */
860  if (rawDefaults || stmt->constraints)
861  AddRelationNewConstraints(rel, rawDefaults, stmt->constraints,
862  true, true, false);
863 
864  ObjectAddressSet(address, RelationRelationId, relationId);
865 
866  /*
867  * Clean up. We keep lock on new relation (although it shouldn't be
868  * visible to anyone else anyway, until commit).
869  */
870  relation_close(rel, NoLock);
871 
872  return address;
873 }
RangeVar * relation
Definition: parsenodes.h:1987
bytea * heap_reloptions(char relkind, Datum reloptions, bool validate)
Definition: reloptions.c:1409
#define NIL
Definition: pg_list.h:69
Oid get_tablespace_oid(const char *tablespacename, bool missing_ok)
Definition: tablespace.c:1380
OnCommitAction oncommit
Definition: parsenodes.h:1996
List * inhRelations
Definition: parsenodes.h:1989
AclResult pg_tablespace_aclcheck(Oid spc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4496
bool is_no_inherit
Definition: heap.h:38
bool tdhasoid
Definition: tupdesc.h:79
void StorePartitionKey(Relation rel, char strategy, int16 partnatts, AttrNumber *partattrs, List *partexprs, Oid *partopclass, Oid *partcollation)
Definition: heap.c:3086
AttrNumber attnum
Definition: heap.h:24
List * partParams
Definition: parsenodes.h:781
Oid GetUserId(void)
Definition: miscinit.c:283
char identity
Definition: parsenodes.h:649
#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
#define PARTITION_MAX_KEYS
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1260
List * list_concat(List *list1, List *list2)
Definition: list.c:321
#define heap_close(r, l)
Definition: heapam.h:97
Form_pg_class rd_rel
Definition: rel.h:114
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:538
static void StoreCatalogInheritance(Oid relationId, List *supers, bool child_is_partition)
Definition: tablecmds.c:2299
void check_new_partition_bound(char *relname, Relation parent, PartitionBoundSpec *spec)
Definition: partition.c:669
Oid GetDefaultTablespace(char relpersistence)
Definition: tablespace.c:1111
static PartitionSpec * transformPartitionSpec(Relation rel, PartitionSpec *partspec, char *strategy)
Definition: tablecmds.c:13129
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3457
Oid MyDatabaseTableSpace
Definition: globals.c:79
static void ComputePartitionAttrs(Relation rel, List *partParams, AttrNumber *partattrs, List **partexprs, Oid *partopclass, Oid *partcollation)
Definition: tablecmds.c:13212
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:44
bytea * view_reloptions(Datum reloptions, bool validate)
Definition: reloptions.c:1377
List * constraints
Definition: parsenodes.h:1994
PartitionBoundSpec * transformPartitionBound(ParseState *pstate, Relation parent, PartitionBoundSpec *spec)
#define NAMEDATALEN
PartitionBoundSpec * partbound
Definition: parsenodes.h:1991
Node * cooked_default
Definition: parsenodes.h:648
char * relname
Definition: primnodes.h:68
AttrNumber attnum
Definition: heap.h:33
#define ERROR
Definition: elog.h:43
#define ACL_CREATE
Definition: parsenodes.h:82
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:3399
#define RelationGetRelationName(relation)
Definition: rel.h:436
List * options
Definition: parsenodes.h:1995
Node * raw_default
Definition: heap.h:25
#define ACL_USAGE
Definition: parsenodes.h:80
bool skip_validation
Definition: heap.h:35
#define HEAP_RELOPT_NAMESPACES
Definition: reloptions.h:59
const char * p_sourcetext
Definition: parse_node.h:171
ConstrType contype
Definition: heap.h:30
#define ereport(elevel, rest)
Definition: elog.h:122
Node * raw_default
Definition: parsenodes.h:647
List * lappend(List *list, void *datum)
Definition: list.c:128
char * tablespacename
Definition: parsenodes.h:1997
Oid RangeVarGetAndCheckCreationNamespace(RangeVar *relation, LOCKMODE lockmode, Oid *existing_relation_id)
Definition: namespace.c:508
#define RELKIND_PARTITIONED_TABLE
Definition: pg_class.h:168
AclResult
Definition: acl.h:170
uintptr_t Datum
Definition: postgres.h:372
void CommandCounterIncrement(void)
Definition: xact.c:922
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
Datum transformRelOptions(Datum oldOptions, List *defList, char *namspace, char *validnsps[], bool ignoreOids, bool isReset)
Definition: reloptions.c:745
bool allowSystemTableMods
Definition: globals.c:112
#define InvalidOid
Definition: postgres_ext.h:36
void StorePartitionBound(Relation rel, Relation parent, PartitionBoundSpec *bound)
Definition: heap.c:3227
List * tableElts
Definition: parsenodes.h:1988
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#define lfirst(lc)
Definition: pg_list.h:106
#define StrNCpy(dst, src, len)
Definition: c.h:830
bool InSecurityRestrictedOperation(void)
Definition: miscinit.c:415
#define linitial_oid(l)
Definition: pg_list.h:113
static int list_length(const List *l)
Definition: pg_list.h:89
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
char relpersistence
Definition: primnodes.h:71
bool interpretOidsOption(List *defList, bool allowOids)
Definition: parse_clause.c:255
static List * MergeAttributes(List *schema, List *supers, char relpersistence, bool is_partition, List **supOids, List **supconstr, int *supOidCount)
Definition: tablecmds.c:1621
#define AccessExclusiveLock
Definition: lockdefs.h:45
void * palloc(Size size)
Definition: mcxt.c:849
int errmsg(const char *fmt,...)
Definition: elog.c:797
char * get_tablespace_name(Oid spc_oid)
Definition: tablespace.c:1426
#define RELKIND_VIEW
Definition: pg_class.h:164
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:1019
Oid conoid
Definition: heap.h:31
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1114
Node * expr
Definition: heap.h:34
#define elog
Definition: elog.h:219
TupleDesc BuildDescForRelation(List *schema)
Definition: tupdesc.c:681
#define RELPERSISTENCE_TEMP
Definition: pg_class.h:172
AclResult pg_type_aclcheck(Oid type_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4534
#define RELKIND_RELATION
Definition: pg_class.h:160
PartitionSpec * partspec
Definition: parsenodes.h:1992
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:2201
TypeName * ofTypename
Definition: parsenodes.h:1993
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 1196 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, errcode(), errhint(), errmsg(), ERROR, 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::inh, InitResultRelInfo(), 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(), RELKIND_PARTITIONED_TABLE, RELPERSISTENCE_UNLOGGED, ResetSequence(), TruncateStmt::restart_seqs, and truncate_check_rel().

Referenced by standard_ProcessUtility().

1197 {
1198  List *rels = NIL;
1199  List *relids = NIL;
1200  List *seq_relids = NIL;
1201  EState *estate;
1202  ResultRelInfo *resultRelInfos;
1203  ResultRelInfo *resultRelInfo;
1204  SubTransactionId mySubid;
1205  ListCell *cell;
1206 
1207  /*
1208  * Open, exclusive-lock, and check all the explicitly-specified relations
1209  */
1210  foreach(cell, stmt->relations)
1211  {
1212  RangeVar *rv = lfirst(cell);
1213  Relation rel;
1214  bool recurse = rv->inh;
1215  Oid myrelid;
1216 
1217  rel = heap_openrv(rv, AccessExclusiveLock);
1218  myrelid = RelationGetRelid(rel);
1219  /* don't throw error for "TRUNCATE foo, foo" */
1220  if (list_member_oid(relids, myrelid))
1221  {
1223  continue;
1224  }
1225  truncate_check_rel(rel);
1226  rels = lappend(rels, rel);
1227  relids = lappend_oid(relids, myrelid);
1228 
1229  if (recurse)
1230  {
1231  ListCell *child;
1232  List *children;
1233 
1234  children = find_all_inheritors(myrelid, AccessExclusiveLock, NULL);
1235 
1236  foreach(child, children)
1237  {
1238  Oid childrelid = lfirst_oid(child);
1239 
1240  if (list_member_oid(relids, childrelid))
1241  continue;
1242 
1243  /* find_all_inheritors already got lock */
1244  rel = heap_open(childrelid, NoLock);
1245  truncate_check_rel(rel);
1246  rels = lappend(rels, rel);
1247  relids = lappend_oid(relids, childrelid);
1248  }
1249  }
1250  else if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1251  ereport(ERROR,
1252  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1253  errmsg("cannot truncate only a partitioned table"),
1254  errhint("Do not specify the ONLY keyword, or use truncate only on the partitions directly.")));
1255  }
1256 
1257  /*
1258  * In CASCADE mode, suck in all referencing relations as well. This
1259  * requires multiple iterations to find indirectly-dependent relations. At
1260  * each phase, we need to exclusive-lock new rels before looking for their
1261  * dependencies, else we might miss something. Also, we check each rel as
1262  * soon as we open it, to avoid a faux pas such as holding lock for a long
1263  * time on a rel we have no permissions for.
1264  */
1265  if (stmt->behavior == DROP_CASCADE)
1266  {
1267  for (;;)
1268  {
1269  List *newrelids;
1270 
1271  newrelids = heap_truncate_find_FKs(relids);
1272  if (newrelids == NIL)
1273  break; /* nothing else to add */
1274 
1275  foreach(cell, newrelids)
1276  {
1277  Oid relid = lfirst_oid(cell);
1278  Relation rel;
1279 
1280  rel = heap_open(relid, AccessExclusiveLock);
1281  ereport(NOTICE,
1282  (errmsg("truncate cascades to table \"%s\"",
1283  RelationGetRelationName(rel))));
1284  truncate_check_rel(rel);
1285  rels = lappend(rels, rel);
1286  relids = lappend_oid(relids, relid);
1287  }
1288  }
1289  }
1290 
1291  /*
1292  * Check foreign key references. In CASCADE mode, this should be
1293  * unnecessary since we just pulled in all the references; but as a
1294  * cross-check, do it anyway if in an Assert-enabled build.
1295  */
1296 #ifdef USE_ASSERT_CHECKING
1297  heap_truncate_check_FKs(rels, false);
1298 #else
1299  if (stmt->behavior == DROP_RESTRICT)
1300  heap_truncate_check_FKs(rels, false);
1301 #endif
1302 
1303  /*
1304  * If we are asked to restart sequences, find all the sequences, lock them
1305  * (we need AccessExclusiveLock for ResetSequence), and check permissions.
1306  * We want to do this early since it's pointless to do all the truncation
1307  * work only to fail on sequence permissions.
1308  */
1309  if (stmt->restart_seqs)
1310  {
1311  foreach(cell, rels)
1312  {
1313  Relation rel = (Relation) lfirst(cell);
1314  List *seqlist = getOwnedSequences(RelationGetRelid(rel), 0);
1315  ListCell *seqcell;
1316 
1317  foreach(seqcell, seqlist)
1318  {
1319  Oid seq_relid = lfirst_oid(seqcell);
1320  Relation seq_rel;
1321 
1322  seq_rel = relation_open(seq_relid, AccessExclusiveLock);
1323 
1324  /* This check must match AlterSequence! */
1325  if (!pg_class_ownercheck(seq_relid, GetUserId()))
1327  RelationGetRelationName(seq_rel));
1328 
1329  seq_relids = lappend_oid(seq_relids, seq_relid);
1330 
1331  relation_close(seq_rel, NoLock);
1332  }
1333  }
1334  }
1335 
1336  /* Prepare to catch AFTER triggers. */
1338 
1339  /*
1340  * To fire triggers, we'll need an EState as well as a ResultRelInfo for
1341  * each relation. We don't need to call ExecOpenIndices, though.
1342  */
1343  estate = CreateExecutorState();
1344  resultRelInfos = (ResultRelInfo *)
1345  palloc(list_length(rels) * sizeof(ResultRelInfo));
1346  resultRelInfo = resultRelInfos;
1347  foreach(cell, rels)
1348  {
1349  Relation rel = (Relation) lfirst(cell);
1350 
1351  InitResultRelInfo(resultRelInfo,
1352  rel,
1353  0, /* dummy rangetable index */
1354  NULL,
1355  0);
1356  resultRelInfo++;
1357  }
1358  estate->es_result_relations = resultRelInfos;
1359  estate->es_num_result_relations = list_length(rels);
1360 
1361  /*
1362  * Process all BEFORE STATEMENT TRUNCATE triggers before we begin
1363  * truncating (this is because one of them might throw an error). Also, if
1364  * we were to allow them to prevent statement execution, that would need
1365  * to be handled here.
1366  */
1367  resultRelInfo = resultRelInfos;
1368  foreach(cell, rels)
1369  {
1370  estate->es_result_relation_info = resultRelInfo;
1371  ExecBSTruncateTriggers(estate, resultRelInfo);
1372  resultRelInfo++;
1373  }
1374 
1375  /*
1376  * OK, truncate each table.
1377  */
1378  mySubid = GetCurrentSubTransactionId();
1379 
1380  foreach(cell, rels)
1381  {
1382  Relation rel = (Relation) lfirst(cell);
1383 
1384  /* Skip partitioned tables as there is nothing to do */
1385  if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1386  continue;
1387 
1388  /*
1389  * Normally, we need a transaction-safe truncation here. However, if
1390  * the table was either created in the current (sub)transaction or has
1391  * a new relfilenode in the current (sub)transaction, then we can just
1392  * truncate it in-place, because a rollback would cause the whole
1393  * table or the current physical file to be thrown away anyway.
1394  */
1395  if (rel->rd_createSubid == mySubid ||
1396  rel->rd_newRelfilenodeSubid == mySubid)
1397  {
1398  /* Immediate, non-rollbackable truncation is OK */
1399  heap_truncate_one_rel(rel);
1400  }
1401  else
1402  {
1403  Oid heap_relid;
1404  Oid toast_relid;
1405  MultiXactId minmulti;
1406 
1407  /*
1408  * This effectively deletes all rows in the table, and may be done
1409  * in a serializable transaction. In that case we must record a
1410  * rw-conflict in to this transaction from each transaction
1411  * holding a predicate lock on the table.
1412  */
1414 
1415  minmulti = GetOldestMultiXactId();
1416 
1417  /*
1418  * Need the full transaction-safe pushups.
1419  *
1420  * Create a new empty storage file for the relation, and assign it
1421  * as the relfilenode value. The old storage file is scheduled for
1422  * deletion at commit.
1423  */
1424  RelationSetNewRelfilenode(rel, rel->rd_rel->relpersistence,
1425  RecentXmin, minmulti);
1426  if (rel->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED)
1427  heap_create_init_fork(rel);
1428 
1429  heap_relid = RelationGetRelid(rel);
1430  toast_relid = rel->rd_rel->reltoastrelid;
1431 
1432  /*
1433  * The same for the toast table, if any.
1434  */
1435  if (OidIsValid(toast_relid))
1436  {
1437  rel = relation_open(toast_relid, AccessExclusiveLock);
1438  RelationSetNewRelfilenode(rel, rel->rd_rel->relpersistence,
1439  RecentXmin, minmulti);
1440  if (rel->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED)
1441  heap_create_init_fork(rel);
1442  heap_close(rel, NoLock);
1443  }
1444 
1445  /*
1446  * Reconstruct the indexes to match, and we're done.
1447  */
1449  }
1450 
1451  pgstat_count_truncate(rel);
1452  }
1453 
1454  /*
1455  * Restart owned sequences if we were asked to.
1456  */
1457  foreach(cell, seq_relids)
1458  {
1459  Oid seq_relid = lfirst_oid(cell);
1460 
1461  ResetSequence(seq_relid);
1462  }
1463 
1464  /*
1465  * Process all AFTER STATEMENT TRUNCATE triggers.
1466  */
1467  resultRelInfo = resultRelInfos;
1468  foreach(cell, rels)
1469  {
1470  estate->es_result_relation_info = resultRelInfo;
1471  ExecASTruncateTriggers(estate, resultRelInfo);
1472  resultRelInfo++;
1473  }
1474 
1475  /* Handle queued AFTER triggers */
1476  AfterTriggerEndQuery(estate);
1477 
1478  /* We can clean up the EState now */
1479  FreeExecutorState(estate);
1480 
1481  /* And close the rels (can't do this while EState still holds refs) */
1482  foreach(cell, rels)
1483  {
1484  Relation rel = (Relation) lfirst(cell);
1485 
1486  heap_close(rel, NoLock);
1487  }
1488 }
#define NIL
Definition: pg_list.h:69
void InitResultRelInfo(ResultRelInfo *resultRelInfo, Relation resultRelationDesc, Index resultRelationIndex, Relation partition_root, int instrument_options)
Definition: execMain.c:1299
void RelationSetNewRelfilenode(Relation relation, char persistence, TransactionId freezeXid, MultiXactId minmulti)
Definition: relcache.c:3416
int errhint(const char *fmt,...)
Definition: elog.c:987
#define RELPERSISTENCE_UNLOGGED
Definition: pg_class.h:171
Oid GetUserId(void)
Definition: miscinit.c:283
void heap_truncate_one_rel(Relation rel)
Definition: heap.c:2873
int errcode(int sqlerrcode)
Definition: elog.c:575
TransactionId RecentXmin
Definition: snapmgr.c:165
void heap_truncate_check_FKs(List *relations, bool tempTables)
Definition: heap.c:2910
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1260
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:111
uint32 SubTransactionId
Definition: c.h:401
#define heap_close(r, l)
Definition: heapam.h:97
Form_pg_class rd_rel
Definition: rel.h:114
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
#define OidIsValid(objectId)
Definition: c.h:538
void FreeExecutorState(EState *estate)
Definition: execUtils.c:178
DropBehavior behavior
Definition: parsenodes.h:2578
struct RelationData * Relation
Definition: relcache.h:21
void ExecBSTruncateTriggers(EState *estate, ResultRelInfo *relinfo)
Definition: trigger.c:2833
#define ERROR
Definition: elog.h:43
struct ResultRelInfo ResultRelInfo
List * relations
Definition: parsenodes.h:2576
#define NoLock
Definition: lockdefs.h:34
void heap_create_init_fork(Relation rel)
Definition: heap.c:1380
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3399
ResultRelInfo * es_result_relations
Definition: execnodes.h:441
bool restart_seqs
Definition: parsenodes.h:2577
void ExecASTruncateTriggers(EState *estate, ResultRelInfo *relinfo)
Definition: trigger.c:2885
#define RelationGetRelationName(relation)
Definition: rel.h:436
void pgstat_count_truncate(Relation rel)
Definition: pgstat.c:2008
#define ereport(elevel, rest)
Definition: elog.h:122
EState * CreateExecutorState(void)
Definition: execUtils.c:80
bool inh
Definition: primnodes.h:69
List * lappend(List *list, void *datum)
Definition: list.c:128
SubTransactionId rd_createSubid
Definition: rel.h:110
#define RELKIND_PARTITIONED_TABLE
Definition: pg_class.h:168
MultiXactId GetOldestMultiXactId(void)
Definition: multixact.c:2491
List * getOwnedSequences(Oid relid, AttrNumber attnum)
Definition: pg_depend.c:548
static void truncate_check_rel(Relation rel)
Definition: tablecmds.c:1494
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
int es_num_result_relations
Definition: execnodes.h:442
Relation heap_openrv(const RangeVar *relation, LOCKMODE lockmode)
Definition: heapam.c:1312
#define NOTICE
Definition: elog.h:37
void AfterTriggerBeginQuery(void)
Definition: trigger.c:4167
TransactionId MultiXactId
Definition: c.h:407
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:505
#define NULL
Definition: c.h:229
#define lfirst(lc)
Definition: pg_list.h:106
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:649
bool pg_class_ownercheck(Oid class_oid, Oid roleid)
Definition: aclchk.c:4546
static int list_length(const List *l)
Definition: pg_list.h:89
void CheckTableForSerializableConflictIn(Relation relation)
Definition: predicate.c:4395
#define AccessExclusiveLock
Definition: lockdefs.h:45
List * find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents)
Definition: pg_inherits.c:167
void AfterTriggerEndQuery(EState *estate)
Definition: trigger.c:4187
void * palloc(Size size)
Definition: mcxt.c:849
int errmsg(const char *fmt,...)
Definition: elog.c:797
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1114
#define REINDEX_REL_PROCESS_TOAST
Definition: index.h:122
void ResetSequence(Oid seq_relid)
Definition: sequence.c:269
bool reindex_relation(Oid relid, int flags, int options)
Definition: index.c:3509
Definition: pg_list.h:45
#define RelationGetRelid(relation)
Definition: rel.h:416
List * heap_truncate_find_FKs(List *relationIds)
Definition: heap.c:3002
#define lfirst_oid(lc)
Definition: pg_list.h:108
ResultRelInfo * es_result_relation_info
Definition: execnodes.h:443
void find_composite_type_dependencies ( Oid  typeOid,
Relation  origRelation,
const char *  origTypeName 
)

Definition at line 4864 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_PARTITIONED_TABLE, RELKIND_RELATION, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), and TypeRelationId.

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

4866 {
4867  Relation depRel;
4868  ScanKeyData key[2];
4869  SysScanDesc depScan;
4870  HeapTuple depTup;
4871  Oid arrayOid;
4872 
4873  /*
4874  * We scan pg_depend to find those things that depend on the rowtype. (We
4875  * assume we can ignore refobjsubid for a rowtype.)
4876  */
4878 
4879  ScanKeyInit(&key[0],
4881  BTEqualStrategyNumber, F_OIDEQ,
4883  ScanKeyInit(&key[1],
4885  BTEqualStrategyNumber, F_OIDEQ,
4886  ObjectIdGetDatum(typeOid));
4887 
4888  depScan = systable_beginscan(depRel, DependReferenceIndexId, true,
4889  NULL, 2, key);
4890 
4891  while (HeapTupleIsValid(depTup = systable_getnext(depScan)))
4892  {
4893  Form_pg_depend pg_depend = (Form_pg_depend) GETSTRUCT(depTup);
4894  Relation rel;
4895  Form_pg_attribute att;
4896 
4897  /* Ignore dependees that aren't user columns of relations */
4898  /* (we assume system columns are never of rowtypes) */
4899  if (pg_depend->classid != RelationRelationId ||
4900  pg_depend->objsubid <= 0)
4901  continue;
4902 
4903  rel = relation_open(pg_depend->objid, AccessShareLock);
4904  att = rel->rd_att->attrs[pg_depend->objsubid - 1];
4905 
4906  if (rel->rd_rel->relkind == RELKIND_RELATION ||
4907  rel->rd_rel->relkind == RELKIND_MATVIEW ||
4908  rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
4909  {
4910  if (origTypeName)
4911  ereport(ERROR,
4912  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4913  errmsg("cannot alter type \"%s\" because column \"%s.%s\" uses it",
4914  origTypeName,
4916  NameStr(att->attname))));
4917  else if (origRelation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
4918  ereport(ERROR,
4919  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4920  errmsg("cannot alter type \"%s\" because column \"%s.%s\" uses it",
4921  RelationGetRelationName(origRelation),
4923  NameStr(att->attname))));
4924  else if (origRelation->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
4925  ereport(ERROR,
4926  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4927  errmsg("cannot alter foreign table \"%s\" because column \"%s.%s\" uses its row type",
4928  RelationGetRelationName(origRelation),
4930  NameStr(att->attname))));
4931  else
4932  ereport(ERROR,
4933  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4934  errmsg("cannot alter table \"%s\" because column \"%s.%s\" uses its row type",
4935  RelationGetRelationName(origRelation),
4937  NameStr(att->attname))));
4938  }
4939  else if (OidIsValid(rel->rd_rel->reltype))
4940  {
4941  /*
4942  * A view or composite type itself isn't a problem, but we must
4943  * recursively check for indirect dependencies via its rowtype.
4944  */
4946  origRelation, origTypeName);
4947  }
4948 
4950  }
4951 
4952  systable_endscan(depScan);
4953 
4955 
4956  /*
4957  * If there's an array type for the rowtype, must check for uses of it,
4958  * too.
4959  */
4960  arrayOid = get_array_type(typeOid);
4961  if (OidIsValid(arrayOid))
4962  find_composite_type_dependencies(arrayOid, origRelation, origTypeName);
4963 }
#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:499
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
Oid get_array_type(Oid typid)
Definition: lsyscache.c:2512
#define RelationRelationId
Definition: pg_class.h:29
#define DependReferenceIndexId
Definition: indexing.h:147
void find_composite_type_dependencies(Oid typeOid, Relation origRelation, const char *origTypeName)
Definition: tablecmds.c:4864
#define DependRelationId
Definition: pg_depend.h:29
Form_pg_attribute * attrs
Definition: tupdesc.h:74
#define RELKIND_MATVIEW
Definition: pg_class.h:165
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:575
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1260
Form_pg_class rd_rel
Definition: rel.h:114
unsigned int Oid
Definition: postgres_ext.h:31
#define TypeRelationId
Definition: pg_type.h:34
#define OidIsValid(objectId)
Definition: c.h:538
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:328
#define RELKIND_COMPOSITE_TYPE
Definition: pg_class.h:166
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define RelationGetRelationName(relation)
Definition: rel.h:436
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
#define RELKIND_FOREIGN_TABLE
Definition: pg_class.h:167
FormData_pg_depend * Form_pg_depend
Definition: pg_depend.h:61
#define ereport(elevel, rest)
Definition: elog.h:122
#define RELKIND_PARTITIONED_TABLE
Definition: pg_class.h:168
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
TupleDesc rd_att
Definition: rel.h:115
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define NameStr(name)
Definition: c.h:499
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:1114
#define RELKIND_RELATION
Definition: pg_class.h:160
#define BTEqualStrategyNumber
Definition: stratnum.h:31
void PreCommit_on_commit_actions ( void  )

Definition at line 12780 of file tablecmds.c.

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

Referenced by CommitTransaction(), and PrepareTransaction().

12781 {
12782  ListCell *l;
12783  List *oids_to_truncate = NIL;
12784 
12785  foreach(l, on_commits)
12786  {
12787  OnCommitItem *oc = (OnCommitItem *) lfirst(l);
12788 
12789  /* Ignore entry if already dropped in this xact */
12791  continue;
12792 
12793  switch (oc->oncommit)
12794  {
12795  case ONCOMMIT_NOOP:
12797  /* Do nothing (there shouldn't be such entries, actually) */
12798  break;
12799  case ONCOMMIT_DELETE_ROWS:
12800 
12801  /*
12802  * If this transaction hasn't accessed any temporary
12803  * relations, we can skip truncating ON COMMIT DELETE ROWS
12804  * tables, as they must still be empty.
12805  */
12807  oids_to_truncate = lappend_oid(oids_to_truncate, oc->relid);
12808  break;
12809  case ONCOMMIT_DROP:
12810  {
12811  ObjectAddress object;
12812 
12813  object.classId = RelationRelationId;
12814  object.objectId = oc->relid;
12815  object.objectSubId = 0;
12816 
12817  /*
12818  * Since this is an automatic drop, rather than one
12819  * directly initiated by the user, we pass the
12820  * PERFORM_DELETION_INTERNAL flag.
12821  */
12822  performDeletion(&object,
12824 
12825  /*
12826  * Note that table deletion will call
12827  * remove_on_commit_action, so the entry should get marked
12828  * as deleted.
12829  */
12831  break;
12832  }
12833  }
12834  }
12835  if (oids_to_truncate != NIL)
12836  {
12837  heap_truncate(oids_to_truncate);
12838  CommandCounterIncrement(); /* XXX needed? */
12839  }
12840 }
#define NIL
Definition: pg_list.h:69
OnCommitAction oncommit
Definition: tablecmds.c:111
#define RelationRelationId
Definition: pg_class.h:29
#define XACT_FLAGS_ACCESSEDTEMPREL
Definition: xact.h:86
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
static List * on_commits
Definition: tablecmds.c:124
void performDeletion(const ObjectAddress *object, DropBehavior behavior, int flags)
Definition: dependency.c:303
int MyXactFlags
Definition: xact.c:118
SubTransactionId deleting_subid
Definition: tablecmds.c:121
void CommandCounterIncrement(void)
Definition: xact.c:922
#define Assert(condition)
Definition: c.h:675
#define lfirst(lc)
Definition: pg_list.h:106
void heap_truncate(List *relids)
Definition: heap.c:2832
#define InvalidSubTransactionId
Definition: c.h:403
Definition: pg_list.h:45
#define PERFORM_DELETION_INTERNAL
Definition: dependency.h:174
void RangeVarCallbackOwnsRelation ( const RangeVar relation,
Oid  relId,
Oid  oldRelId,
void *  noCatalogs 
)

Definition at line 12971 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 AlterSequence(), and ProcessUtilitySlow().

12973 {
12974  HeapTuple tuple;
12975 
12976  /* Nothing to do if the relation was not found. */
12977  if (!OidIsValid(relId))
12978  return;
12979 
12980  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relId));
12981  if (!HeapTupleIsValid(tuple)) /* should not happen */
12982  elog(ERROR, "cache lookup failed for relation %u", relId);
12983 
12984  if (!pg_class_ownercheck(relId, GetUserId()))
12986  relation->relname);
12987 
12988  if (!allowSystemTableMods &&
12989  IsSystemClass(relId, (Form_pg_class) GETSTRUCT(tuple)))
12990  ereport(ERROR,
12991  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
12992  errmsg("permission denied: \"%s\" is a system catalog",
12993  relation->relname)));
12994 
12995  ReleaseSysCache(tuple);
12996 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
Oid GetUserId(void)
Definition: miscinit.c:283
int errcode(int sqlerrcode)
Definition: elog.c:575
#define OidIsValid(objectId)
Definition: c.h:538
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:156
bool IsSystemClass(Oid relid, Form_pg_class reltuple)
Definition: catalog.c:75
char * relname
Definition: primnodes.h:68
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3399
#define ereport(elevel, rest)
Definition: elog.h:122
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
bool allowSystemTableMods
Definition: globals.c:112
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
bool pg_class_ownercheck(Oid class_oid, Oid roleid)
Definition: aclchk.c:4546
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
void RangeVarCallbackOwnsTable ( const RangeVar relation,
Oid  relId,
Oid  oldRelId,
void *  arg 
)

Definition at line 12938 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_PARTITIONED_TABLE, RELKIND_RELATION, RELKIND_TOASTVALUE, and RangeVar::relname.

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

12940 {
12941  char relkind;
12942 
12943  /* Nothing to do if the relation was not found. */
12944  if (!OidIsValid(relId))
12945  return;
12946 
12947  /*
12948  * If the relation does exist, check whether it's an index. But note that
12949  * the relation might have been dropped between the time we did the name
12950  * lookup and now. In that case, there's nothing to do.
12951  */
12952  relkind = get_rel_relkind(relId);
12953  if (!relkind)
12954  return;
12955  if (relkind != RELKIND_RELATION && relkind != RELKIND_TOASTVALUE &&
12956  relkind != RELKIND_MATVIEW && relkind != RELKIND_PARTITIONED_TABLE)
12957  ereport(ERROR,
12958  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
12959  errmsg("\"%s\" is not a table or materialized view", relation->relname)));
12960 
12961  /* Check permissions */
12962  if (!pg_class_ownercheck(relId, GetUserId()))
12964 }
Oid GetUserId(void)
Definition: miscinit.c:283
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:1801
#define RELKIND_MATVIEW
Definition: pg_class.h:165
int errcode(int sqlerrcode)
Definition: elog.c:575
#define OidIsValid(objectId)
Definition: c.h:538
char * relname
Definition: primnodes.h:68
#define ERROR
Definition: elog.h:43
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3399
#define ereport(elevel, rest)
Definition: elog.h:122
#define RELKIND_PARTITIONED_TABLE
Definition: pg_class.h:168
#define RELKIND_TOASTVALUE
Definition: pg_class.h:163
bool pg_class_ownercheck(Oid class_oid, Oid roleid)
Definition: aclchk.c:4546
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define RELKIND_RELATION
Definition: pg_class.h:160
void register_on_commit_action ( Oid  relid,
OnCommitAction  action 
)

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

12727 {
12728  OnCommitItem *oc;
12729  MemoryContext oldcxt;
12730 
12731  /*
12732  * We needn't bother registering the relation unless there is an ON COMMIT
12733  * action we need to take.
12734  */
12735  if (action == ONCOMMIT_NOOP || action == ONCOMMIT_PRESERVE_ROWS)
12736  return;
12737 
12739 
12740  oc = (OnCommitItem *) palloc(sizeof(OnCommitItem));
12741  oc->relid = relid;
12742  oc->oncommit = action;
12745 
12746  on_commits = lcons(oc, on_commits);
12747 
12748  MemoryContextSwitchTo(oldcxt);
12749 }
OnCommitAction oncommit
Definition: tablecmds.c:111
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
SubTransactionId creating_subid
Definition: tablecmds.c:120
static List * on_commits
Definition: tablecmds.c:124
SubTransactionId deleting_subid
Definition: tablecmds.c:121
List * lcons(void *datum, List *list)
Definition: list.c:259
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:649
#define InvalidSubTransactionId
Definition: c.h:403
void * palloc(Size size)
Definition: mcxt.c:849
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
void remove_on_commit_action ( Oid  relid)

Definition at line 12757 of file tablecmds.c.

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

Referenced by heap_drop_with_catalog().

12758 {
12759  ListCell *l;
12760 
12761  foreach(l, on_commits)
12762  {
12763  OnCommitItem *oc = (OnCommitItem *) lfirst(l);
12764 
12765  if (oc->relid == relid)
12766  {
12768  break;
12769  }
12770  }
12771 }
static List * on_commits
Definition: tablecmds.c:124
SubTransactionId deleting_subid
Definition: tablecmds.c:121
#define lfirst(lc)
Definition: pg_list.h:106
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:649
void RemoveRelations ( DropStmt drop)

Definition at line 955 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, DropRelationCallbackState::partParentOid, 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().

956 {
957  ObjectAddresses *objects;
958  char relkind;
959  ListCell *cell;
960  int flags = 0;
961  LOCKMODE lockmode = AccessExclusiveLock;
962 
963  /* DROP CONCURRENTLY uses a weaker lock, and has some restrictions */
964  if (drop->concurrent)
965  {
967  lockmode = ShareUpdateExclusiveLock;
968  Assert(drop->removeType == OBJECT_INDEX);
969  if (list_length(drop->objects) != 1)
970  ereport(ERROR,
971  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
972  errmsg("DROP INDEX CONCURRENTLY does not support dropping multiple objects")));
973  if (drop->behavior == DROP_CASCADE)
974  ereport(ERROR,
975  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
976  errmsg("DROP INDEX CONCURRENTLY does not support CASCADE")));
977  }
978 
979  /*
980  * First we identify all the relations, then we delete them in a single
981  * performMultipleDeletions() call. This is to avoid unwanted DROP
982  * RESTRICT errors if one of the relations depends on another.
983  */
984 
985  /* Determine required relkind */
986  switch (drop->removeType)
987  {
988  case OBJECT_TABLE:
989  relkind = RELKIND_RELATION;
990  break;
991 
992  case OBJECT_INDEX:
993  relkind = RELKIND_INDEX;
994  break;
995 
996  case OBJECT_SEQUENCE:
997  relkind = RELKIND_SEQUENCE;
998  break;
999 
1000  case OBJECT_VIEW:
1001  relkind = RELKIND_VIEW;
1002  break;
1003 
1004  case OBJECT_MATVIEW:
1005  relkind = RELKIND_MATVIEW;
1006  break;
1007 
1008  case OBJECT_FOREIGN_TABLE:
1009  relkind = RELKIND_FOREIGN_TABLE;
1010  break;
1011 
1012  default:
1013  elog(ERROR, "unrecognized drop object type: %d",
1014  (int) drop->removeType);
1015  relkind = 0; /* keep compiler quiet */
1016  break;
1017  }
1018 
1019  /* Lock and validate each relation; build a list of object addresses */
1020  objects = new_object_addresses();
1021 
1022  foreach(cell, drop->objects)
1023  {
1024  RangeVar *rel = makeRangeVarFromNameList((List *) lfirst(cell));
1025  Oid relOid;
1026  ObjectAddress obj;
1028 
1029  /*
1030  * These next few steps are a great deal like relation_openrv, but we
1031  * don't bother building a relcache entry since we don't need it.
1032  *
1033  * Check for shared-cache-inval messages before trying to access the
1034  * relation. This is needed to cover the case where the name
1035  * identifies a rel that has been dropped and recreated since the
1036  * start of our transaction: if we don't flush the old syscache entry,
1037  * then we'll latch onto that entry and suffer an error later.
1038  */
1040 
1041  /* Look up the appropriate relation using namespace search. */
1042  state.relkind = relkind;
1043  state.heapOid = InvalidOid;
1044  state.partParentOid = InvalidOid;
1045  state.concurrent = drop->concurrent;
1046  relOid = RangeVarGetRelidExtended(rel, lockmode, true,
1047  false,
1049  (void *) &state);
1050 
1051  /* Not there? */
1052  if (!OidIsValid(relOid))
1053  {
1054  DropErrorMsgNonExistent(rel, relkind, drop->missing_ok);
1055  continue;
1056  }
1057 
1058  /* OK, we're ready to delete this one */
1060  obj.objectId = relOid;
1061  obj.objectSubId = 0;
1062 
1063  add_exact_object_address(&obj, objects);
1064  }
1065 
1066  performMultipleDeletions(objects, drop->behavior, flags);
1067 
1068  free_object_addresses(objects);
1069 }
void AcceptInvalidationMessages(void)
Definition: inval.c:679
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:218
#define RelationRelationId
Definition: pg_class.h:29
List * objects
Definition: parsenodes.h:2562
bool missing_ok
Definition: parsenodes.h:2565
#define RELKIND_MATVIEW
Definition: pg_class.h:165
int errcode(int sqlerrcode)
Definition: elog.c:575
RangeVar * makeRangeVarFromNameList(List *names)
Definition: namespace.c:3023
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2107
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2052
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2323
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:538
ObjectType removeType
Definition: parsenodes.h:2563
#define PERFORM_DELETION_CONCURRENTLY
Definition: dependency.h:175
#define ERROR
Definition: elog.h:43
bool concurrent
Definition: parsenodes.h:2566
DropBehavior behavior
Definition: parsenodes.h:2564
#define RELKIND_FOREIGN_TABLE
Definition: pg_class.h:167
#define ereport(elevel, rest)
Definition: elog.h:122
static void RangeVarCallbackForDropRelation(const RangeVar *rel, Oid relOid, Oid oldRelOid, void *arg)
Definition: tablecmds.c:1078
#define InvalidOid
Definition: postgres_ext.h:36
#define ShareUpdateExclusiveLock
Definition: lockdefs.h:39
#define Assert(condition)
Definition: c.h:675
#define lfirst(lc)
Definition: pg_list.h:106
Definition: regguts.h:298
static int list_length(const List *l)
Definition: pg_list.h:89
#define AccessExclusiveLock
Definition: lockdefs.h:45
static void DropErrorMsgNonExistent(RangeVar *rel, char rightkind, bool missing_ok)
Definition: tablecmds.c:880
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define RELKIND_VIEW
Definition: pg_class.h:164
#define RELKIND_INDEX
Definition: pg_class.h:161
void performMultipleDeletions(const ObjectAddresses *objects, DropBehavior behavior, int flags)
Definition: dependency.c:362
#define elog
Definition: elog.h:219
#define RELKIND_RELATION
Definition: pg_class.h:160
#define RELKIND_SEQUENCE
Definition: pg_class.h:162
Definition: pg_list.h:45
ObjectAddress renameatt ( RenameStmt stmt)

Definition at line 2682 of file tablecmds.c.

References AccessExclusiveLock, RenameStmt::behavior, ereport, errmsg(), RangeVar::inh, 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().

2683 {
2684  Oid relid;
2685  AttrNumber attnum;
2686  ObjectAddress address;
2687 
2688  /* lock level taken here should match renameatt_internal */
2690  stmt->missing_ok, false,
2692  NULL);
2693 
2694  if (!OidIsValid(relid))
2695  {
2696  ereport(NOTICE,
2697  (errmsg("relation \"%s\" does not exist, skipping",
2698  stmt->relation->relname)));
2699  return InvalidObjectAddress;
2700  }
2701 
2702  attnum =
2703  renameatt_internal(relid,
2704  stmt->subname, /* old att name */
2705  stmt->newname, /* new att name */
2706  stmt->relation->inh, /* recursive? */
2707  false, /* recursing? */
2708  0, /* expected inhcount */
2709  stmt->behavior);
2710 
2711  ObjectAddressSubSet(address, RelationRelationId, relid, attnum);
2712 
2713  return address;
2714 }
char * subname
Definition: parsenodes.h:2790
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, bool missing_ok, bool nowait, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:218
#define RelationRelationId
Definition: pg_class.h:29
char * newname
Definition: parsenodes.h:2792
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:538
char * relname
Definition: primnodes.h:68
bool missing_ok
Definition: parsenodes.h:2794
#define ereport(elevel, rest)
Definition: elog.h:122
bool inh
Definition: primnodes.h:69
RangeVar * relation
Definition: parsenodes.h:2788
#define NOTICE
Definition: elog.h:37
static void RangeVarCallbackForRenameAttribute(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg)
Definition: tablecmds.c:2662
#define NULL
Definition: c.h:229
static AttrNumber renameatt_internal(Oid myrelid, const char *oldattname, const char *newattname, bool recurse, bool recursing, int expected_parents, DropBehavior behavior)
Definition: tablecmds.c:2517
#define ObjectAddressSubSet(addr, class_id, object_id, object_sub_id)
Definition: objectaddress.h:33
#define AccessExclusiveLock
Definition: lockdefs.h:45
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:797
DropBehavior behavior
Definition: parsenodes.h:2793
int16 AttrNumber
Definition: attnum.h:21
ObjectAddress renameatt_type ( RenameStmt stmt)
ObjectAddress RenameConstraint ( RenameStmt stmt)

Definition at line 2819 of file tablecmds.c.

References AccessExclusiveLock, castNode, checkDomainOwner(), elog, ereport, errmsg(), ERROR, heap_close, heap_open(), HeapTupleIsValid, RangeVar::inh, 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().

2820 {
2821  Oid relid = InvalidOid;
2822  Oid typid = InvalidOid;
2823 
2824  if (stmt->renameType == OBJECT_DOMCONSTRAINT)
2825  {
2826  Relation rel;
2827  HeapTuple tup;
2828 
2831  tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2832  if (!HeapTupleIsValid(tup))
2833  elog(ERROR, "cache lookup failed for type %u", typid);
2834  checkDomainOwner(tup);
2835  ReleaseSysCache(tup);
2836  heap_close(rel, NoLock);
2837  }
2838  else
2839  {
2840  /* lock level taken here should match rename_constraint_internal */
2842  stmt->missing_ok, false,
2844  NULL);
2845  if (!OidIsValid(relid))
2846  {
2847  ereport(NOTICE,
2848  (errmsg("relation \"%s\" does not exist, skipping",
2849  stmt->relation->relname)));
2850  return InvalidObjectAddress;
2851  }
2852  }
2853 
2854  return
2855  rename_constraint_internal(relid, typid,
2856  stmt->subname,
2857  stmt->newname,
2858  (stmt->relation &&
2859  stmt->relation->inh), /* recursive? */
2860  false, /* recursing? */
2861  0 /* expected inhcount */ );
2862 
2863 }
char * subname
Definition: parsenodes.h:2790
ObjectType renameType
Definition: parsenodes.h:2786
#define castNode(_type_, nodeptr)
Definition: nodes.h:578
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, bool missing_ok, bool nowait, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:218
#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:2720
char * newname
Definition: parsenodes.h:2792
unsigned int Oid
Definition: postgres_ext.h:31
#define TypeRelationId
Definition: pg_type.h:34
#define OidIsValid(objectId)
Definition: c.h:538
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:156
char * relname
Definition: primnodes.h:68
bool missing_ok
Definition: parsenodes.h:2794
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
Node * object
Definition: parsenodes.h:2789
#define ereport(elevel, rest)
Definition: elog.h:122
bool inh
Definition: primnodes.h:69
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
RangeVar * relation
Definition: parsenodes.h:2788
#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:2662
#define NULL
Definition: c.h:229
void checkDomainOwner(HeapTuple tup)
Definition: typecmds.c:2952
#define AccessExclusiveLock
Definition: lockdefs.h:45
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:219
Definition: pg_list.h:45
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:274
ObjectAddress RenameRelation ( RenameStmt stmt)

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

2871 {
2872  Oid relid;
2873  ObjectAddress address;
2874 
2875  /*
2876  * Grab an exclusive lock on the target table, index, sequence, view,
2877  * materialized view, or foreign table, which we will NOT release until
2878  * end of transaction.
2879  *
2880  * Lock level used here should match RenameRelationInternal, to avoid lock
2881  * escalation.
2882  */
2884  stmt->missing_ok, false,
2886  (void *) stmt);
2887 
2888  if (!OidIsValid(relid))
2889  {
2890  ereport(NOTICE,
2891  (errmsg("relation \"%s\" does not exist, skipping",
2892  stmt->relation->relname)));
2893  return InvalidObjectAddress;
2894  }
2895 
2896  /* Do the work */
2897  RenameRelationInternal(relid, stmt->newname, false);
2898 
2899  ObjectAddressSet(address, RelationRelationId, relid);
2900 
2901  return address;
2902 }
void RenameRelationInternal(Oid myrelid, const char *newrelname, bool is_internal)
Definition: tablecmds.c:2914
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, bool missing_ok, bool nowait, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:218
#define RelationRelationId
Definition: pg_class.h:29
char * newname
Definition: parsenodes.h:2792
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:538
char * relname
Definition: primnodes.h:68
bool missing_ok
Definition: parsenodes.h:2794
static void RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg)
Definition: tablecmds.c:13003
#define ereport(elevel, rest)
Definition: elog.h:122
RangeVar * relation
Definition: parsenodes.h:2788
#define NOTICE
Definition: elog.h:37
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define AccessExclusiveLock
Definition: lockdefs.h:45
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 2914 of file tablecmds.c.

References AccessExclusiveLock, CatalogTupleUpdate(), 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, and HeapTupleData::t_self.

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

2915 {
2916  Relation targetrelation;
2917  Relation relrelation; /* for RELATION relation */
2918  HeapTuple reltup;
2919  Form_pg_class relform;
2920  Oid namespaceId;
2921 
2922  /*
2923  * Grab an exclusive lock on the target table, index, sequence, view,
2924  * materialized view, or foreign table, which we will NOT release until
2925  * end of transaction.
2926  */
2927  targetrelation = relation_open(myrelid, AccessExclusiveLock);
2928  namespaceId = RelationGetNamespace(targetrelation);
2929 
2930  /*
2931  * Find relation's pg_class tuple, and make sure newrelname isn't in use.
2932  */
2934 
2935  reltup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(myrelid));
2936  if (!HeapTupleIsValid(reltup)) /* shouldn't happen */
2937  elog(ERROR, "cache lookup failed for relation %u", myrelid);
2938  relform = (Form_pg_class) GETSTRUCT(reltup);
2939 
2940  if (get_relname_relid(newrelname, namespaceId) != InvalidOid)
2941  ereport(ERROR,
2942  (errcode(ERRCODE_DUPLICATE_TABLE),
2943  errmsg("relation \"%s\" already exists",
2944  newrelname)));
2945 
2946  /*
2947  * Update pg_class tuple with new relname. (Scribbling on reltup is OK
2948  * because it's a copy...)
2949  */
2950  namestrcpy(&(relform->relname), newrelname);
2951 
2952  CatalogTupleUpdate(relrelation, &reltup->t_self, reltup);
2953 
2955  InvalidOid, is_internal);
2956 
2957  heap_freetuple(reltup);
2958  heap_close(relrelation, RowExclusiveLock);
2959 
2960  /*
2961  * Also rename the associated type, if any.
2962  */
2963  if (OidIsValid(targetrelation->rd_rel->reltype))
2964  RenameTypeInternal(targetrelation->rd_rel->reltype,
2965  newrelname, namespaceId);
2966 
2967  /*
2968  * Also rename the associated constraint, if any.
2969  */
2970  if (targetrelation->rd_rel->relkind == RELKIND_INDEX)
2971  {
2972  Oid constraintId = get_index_constraint(myrelid);
2973 
2974  if (OidIsValid(constraintId))
2975  RenameConstraintById(constraintId, newrelname);
2976  }
2977 
2978  /*
2979  * Close rel, but keep exclusive lock!
2980  */
2981  relation_close(targetrelation, NoLock);
2982 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#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:1260
#define heap_close(r, l)
Definition: heapam.h:97
Form_pg_class rd_rel
Definition: rel.h:114
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1372
unsigned int Oid
Definition: postgres_ext.h:31
int namestrcpy(Name name, const char *str)
Definition: name.c:216
#define OidIsValid(objectId)
Definition: c.h:538
void RenameConstraintById(Oid conId, const char *newname)
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#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:1683
#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:684
#define ereport(elevel, rest)
Definition: elog.h:122
void RenameTypeInternal(Oid typeOid, const char *newTypeName, Oid typeNamespace)
Definition: pg_type.c:692
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:165
#define AccessExclusiveLock
Definition: lockdefs.h:45
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define RELKIND_INDEX
Definition: pg_class.h:161
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1114
#define elog
Definition: elog.h:219
#define RelationGetNamespace(relation)
Definition: rel.h:443
void SetRelationHasSubclass ( Oid  relationId,
bool  relhassubclass 
)

Definition at line 2436 of file tablecmds.c.

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

Referenced by acquire_inherited_sample_rows(), and StoreCatalogInheritance1().

2437 {
2438  Relation relationRelation;
2439  HeapTuple tuple;
2440  Form_pg_class classtuple;
2441 
2442  /*
2443  * Fetch a modifiable copy of the tuple, modify it, update pg_class.
2444  */
2445  relationRelation = heap_open(RelationRelationId, RowExclusiveLock);
2446  tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relationId));
2447  if (!HeapTupleIsValid(tuple))
2448  elog(ERROR, "cache lookup failed for relation %u", relationId);
2449  classtuple = (Form_pg_class) GETSTRUCT(tuple);
2450 
2451  if (classtuple->relhassubclass != relhassubclass)
2452  {
2453  classtuple->relhassubclass = relhassubclass;
2454  CatalogTupleUpdate(relationRelation, &tuple->t_self, tuple);
2455  }
2456  else
2457  {
2458  /* no need to change tuple, but force relcache rebuild anyway */
2460  }
2461 
2462  heap_freetuple(tuple);
2463  heap_close(relationRelation, RowExclusiveLock);
2464 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define RelationRelationId
Definition: pg_class.h:29
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1372
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#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:1284
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:165
void CacheInvalidateRelcacheByTuple(HeapTuple classTuple)
Definition: inval.c:1269
#define elog
Definition: elog.h:219