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

12562 {
12563  HeapTuple classTup;
12564  Form_pg_class classForm;
12565  ObjectAddress thisobj;
12566  bool already_done = false;
12567 
12568  classTup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relOid));
12569  if (!HeapTupleIsValid(classTup))
12570  elog(ERROR, "cache lookup failed for relation %u", relOid);
12571  classForm = (Form_pg_class) GETSTRUCT(classTup);
12572 
12573  Assert(classForm->relnamespace == oldNspOid);
12574 
12575  thisobj.classId = RelationRelationId;
12576  thisobj.objectId = relOid;
12577  thisobj.objectSubId = 0;
12578 
12579  /*
12580  * If the object has already been moved, don't move it again. If it's
12581  * already in the right place, don't move it, but still fire the object
12582  * access hook.
12583  */
12584  already_done = object_address_present(&thisobj, objsMoved);
12585  if (!already_done && oldNspOid != newNspOid)
12586  {
12587  /* check for duplicate name (more friendly than unique-index failure) */
12588  if (get_relname_relid(NameStr(classForm->relname),
12589  newNspOid) != InvalidOid)
12590  ereport(ERROR,
12591  (errcode(ERRCODE_DUPLICATE_TABLE),
12592  errmsg("relation \"%s\" already exists in schema \"%s\"",
12593  NameStr(classForm->relname),
12594  get_namespace_name(newNspOid))));
12595 
12596  /* classTup is a copy, so OK to scribble on */
12597  classForm->relnamespace = newNspOid;
12598 
12599  CatalogTupleUpdate(classRel, &classTup->t_self, classTup);
12600 
12601  /* Update dependency on schema if caller said so */
12602  if (hasDependEntry &&
12604  relOid,
12606  oldNspOid,
12607  newNspOid) != 1)
12608  elog(ERROR, "failed to change schema dependency for relation \"%s\"",
12609  NameStr(classForm->relname));
12610  }
12611  if (!already_done)
12612  {
12613  add_exact_object_address(&thisobj, objsMoved);
12614 
12616  }
12617 
12618  heap_freetuple(classTup);
12619 }
#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:676
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 3094 of file tablecmds.c.

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

Referenced by ProcessUtilitySlow().

3095 {
3096  Relation rel;
3097 
3098  /* Caller is required to provide an adequate lock. */
3099  rel = relation_open(relid, NoLock);
3100 
3101  CheckTableNotInUse(rel, "ALTER TABLE");
3102 
3103  ATController(stmt, rel, stmt->cmds, stmt->relation->inh, lockmode);
3104 }
static void ATController(AlterTableStmt *parsetree, Relation rel, List *cmds, bool recurse, LOCKMODE lockmode)
Definition: tablecmds.c:3411
#define NoLock
Definition: lockdefs.h:34
void CheckTableNotInUse(Relation rel, const char *stmt)
Definition: tablecmds.c:3015
bool inh
Definition: primnodes.h:69
RangeVar * relation
Definition: parsenodes.h:1685
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1120
LOCKMODE AlterTableGetLockLevel ( List cmds)

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

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

Definition at line 3118 of file tablecmds.c.

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

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

3119 {
3120  Relation rel;
3121  LOCKMODE lockmode = AlterTableGetLockLevel(cmds);
3122 
3123  rel = relation_open(relid, lockmode);
3124 
3126 
3127  ATController(NULL, rel, cmds, recurse, lockmode);
3128 }
int LOCKMODE
Definition: lockdefs.h:26
static void ATController(AlterTableStmt *parsetree, Relation rel, List *cmds, bool recurse, LOCKMODE lockmode)
Definition: tablecmds.c:3411
LOCKMODE AlterTableGetLockLevel(List *cmds)
Definition: tablecmds.c:3163
#define NULL
Definition: c.h:229
void EventTriggerAlterTableRelid(Oid objectId)
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1120
Oid AlterTableLookupRelation ( AlterTableStmt stmt,
LOCKMODE  lockmode 
)

Definition at line 3044 of file tablecmds.c.

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

Referenced by ProcessUtilitySlow().

3045 {
3046  return RangeVarGetRelidExtended(stmt->relation, lockmode, stmt->missing_ok, false,
3048  (void *) stmt);
3049 }
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:13035
RangeVar * relation
Definition: parsenodes.h:1685
Oid AlterTableMoveAll ( AlterTableMoveAllStmt stmt)

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

10640 {
10641  List *relations = NIL;
10642  ListCell *l;
10643  ScanKeyData key[1];
10644  Relation rel;
10645  HeapScanDesc scan;
10646  HeapTuple tuple;
10647  Oid orig_tablespaceoid;
10648  Oid new_tablespaceoid;
10649  List *role_oids = roleSpecsToIds(stmt->roles);
10650 
10651  /* Ensure we were not asked to move something we can't */
10652  if (stmt->objtype != OBJECT_TABLE && stmt->objtype != OBJECT_INDEX &&
10653  stmt->objtype != OBJECT_MATVIEW)
10654  ereport(ERROR,
10655  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
10656  errmsg("only tables, indexes, and materialized views exist in tablespaces")));
10657 
10658  /* Get the orig and new tablespace OIDs */
10659  orig_tablespaceoid = get_tablespace_oid(stmt->orig_tablespacename, false);
10660  new_tablespaceoid = get_tablespace_oid(stmt->new_tablespacename, false);
10661 
10662  /* Can't move shared relations in to or out of pg_global */
10663  /* This is also checked by ATExecSetTableSpace, but nice to stop earlier */
10664  if (orig_tablespaceoid == GLOBALTABLESPACE_OID ||
10665  new_tablespaceoid == GLOBALTABLESPACE_OID)
10666  ereport(ERROR,
10667  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
10668  errmsg("cannot move relations in to or out of pg_global tablespace")));
10669 
10670  /*
10671  * Must have CREATE rights on the new tablespace, unless it is the
10672  * database default tablespace (which all users implicitly have CREATE
10673  * rights on).
10674  */
10675  if (OidIsValid(new_tablespaceoid) && new_tablespaceoid != MyDatabaseTableSpace)
10676  {
10677  AclResult aclresult;
10678 
10679  aclresult = pg_tablespace_aclcheck(new_tablespaceoid, GetUserId(),
10680  ACL_CREATE);
10681  if (aclresult != ACLCHECK_OK)
10683  get_tablespace_name(new_tablespaceoid));
10684  }
10685 
10686  /*
10687  * Now that the checks are done, check if we should set either to
10688  * InvalidOid because it is our database's default tablespace.
10689  */
10690  if (orig_tablespaceoid == MyDatabaseTableSpace)
10691  orig_tablespaceoid = InvalidOid;
10692 
10693  if (new_tablespaceoid == MyDatabaseTableSpace)
10694  new_tablespaceoid = InvalidOid;
10695 
10696  /* no-op */
10697  if (orig_tablespaceoid == new_tablespaceoid)
10698  return new_tablespaceoid;
10699 
10700  /*
10701  * Walk the list of objects in the tablespace and move them. This will
10702  * only find objects in our database, of course.
10703  */
10704  ScanKeyInit(&key[0],
10706  BTEqualStrategyNumber, F_OIDEQ,
10707  ObjectIdGetDatum(orig_tablespaceoid));
10708 
10710  scan = heap_beginscan_catalog(rel, 1, key);
10711  while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
10712  {
10713  Oid relOid = HeapTupleGetOid(tuple);
10714  Form_pg_class relForm;
10715 
10716  relForm = (Form_pg_class) GETSTRUCT(tuple);
10717 
10718  /*
10719  * Do not move objects in pg_catalog as part of this, if an admin
10720  * really wishes to do so, they can issue the individual ALTER
10721  * commands directly.
10722  *
10723  * Also, explicitly avoid any shared tables, temp tables, or TOAST
10724  * (TOAST will be moved with the main table).
10725  */
10726  if (IsSystemNamespace(relForm->relnamespace) || relForm->relisshared ||
10727  isAnyTempNamespace(relForm->relnamespace) ||
10728  relForm->relnamespace == PG_TOAST_NAMESPACE)
10729  continue;
10730 
10731  /* Only move the object type requested */
10732  if ((stmt->objtype == OBJECT_TABLE &&
10733  relForm->relkind != RELKIND_RELATION &&
10734  relForm->relkind != RELKIND_PARTITIONED_TABLE) ||
10735  (stmt->objtype == OBJECT_INDEX &&
10736  relForm->relkind != RELKIND_INDEX) ||
10737  (stmt->objtype == OBJECT_MATVIEW &&
10738  relForm->relkind != RELKIND_MATVIEW))
10739  continue;
10740 
10741  /* Check if we are only moving objects owned by certain roles */
10742  if (role_oids != NIL && !list_member_oid(role_oids, relForm->relowner))
10743  continue;
10744 
10745  /*
10746  * Handle permissions-checking here since we are locking the tables
10747  * and also to avoid doing a bunch of work only to fail part-way. Note
10748  * that permissions will also be checked by AlterTableInternal().
10749  *
10750  * Caller must be considered an owner on the table to move it.
10751  */
10752  if (!pg_class_ownercheck(relOid, GetUserId()))
10754  NameStr(relForm->relname));
10755 
10756  if (stmt->nowait &&
10758  ereport(ERROR,
10759  (errcode(ERRCODE_OBJECT_IN_USE),
10760  errmsg("aborting because lock on relation \"%s.%s\" is not available",
10761  get_namespace_name(relForm->relnamespace),
10762  NameStr(relForm->relname))));
10763  else
10765 
10766  /* Add to our list of objects to move */
10767  relations = lappend_oid(relations, relOid);
10768  }
10769 
10770  heap_endscan(scan);
10772 
10773  if (relations == NIL)
10774  ereport(NOTICE,
10775  (errcode(ERRCODE_NO_DATA_FOUND),
10776  errmsg("no matching relations in tablespace \"%s\" found",
10777  orig_tablespaceoid == InvalidOid ? "(database default)" :
10778  get_tablespace_name(orig_tablespaceoid))));
10779 
10780  /* Everything is locked, loop through and move all of the relations. */
10781  foreach(l, relations)
10782  {
10783  List *cmds = NIL;
10785 
10786  cmd->subtype = AT_SetTableSpace;
10787  cmd->name = stmt->new_tablespacename;
10788 
10789  cmds = lappend(cmds, cmd);
10790 
10792  /* OID is set by AlterTableInternal */
10793  AlterTableInternal(lfirst_oid(l), cmds, false);
10795  }
10796 
10797  return new_tablespaceoid;
10798 }
#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:1580
Oid GetUserId(void)
Definition: miscinit.c:284
#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:1772
#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:1405
#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:1810
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
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:1396
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:3118
#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 12449 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().

12450 {
12451  Relation rel;
12452  Oid relid;
12453  Oid oldNspOid;
12454  Oid nspOid;
12455  RangeVar *newrv;
12456  ObjectAddresses *objsMoved;
12457  ObjectAddress myself;
12458 
12460  stmt->missing_ok, false,
12462  (void *) stmt);
12463 
12464  if (!OidIsValid(relid))
12465  {
12466  ereport(NOTICE,
12467  (errmsg("relation \"%s\" does not exist, skipping",
12468  stmt->relation->relname)));
12469  return InvalidObjectAddress;
12470  }
12471 
12472  rel = relation_open(relid, NoLock);
12473 
12474  oldNspOid = RelationGetNamespace(rel);
12475 
12476  /* If it's an owned sequence, disallow moving it by itself. */
12477  if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
12478  {
12479  Oid tableId;
12480  int32 colId;
12481 
12482  if (sequenceIsOwned(relid, DEPENDENCY_AUTO, &tableId, &colId) ||
12483  sequenceIsOwned(relid, DEPENDENCY_INTERNAL, &tableId, &colId))
12484  ereport(ERROR,
12485  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
12486  errmsg("cannot move an owned sequence into another schema"),
12487  errdetail("Sequence \"%s\" is linked to table \"%s\".",
12489  get_rel_name(tableId))));
12490  }
12491 
12492  /* Get and lock schema OID and check its permissions. */
12493  newrv = makeRangeVar(stmt->newschema, RelationGetRelationName(rel), -1);
12495 
12496  /* common checks on switching namespaces */
12497  CheckSetNamespace(oldNspOid, nspOid);
12498 
12499  objsMoved = new_object_addresses();
12500  AlterTableNamespaceInternal(rel, oldNspOid, nspOid, objsMoved);
12501  free_object_addresses(objsMoved);
12502 
12503  ObjectAddressSet(myself, RelationRelationId, relid);
12504 
12505  if (oldschema)
12506  *oldschema = oldNspOid;
12507 
12508  /* close rel, but keep lock until commit */
12509  relation_close(rel, NoLock);
12510 
12511  return myself;
12512 }
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:1266
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:12520
#define NoLock
Definition: lockdefs.h:34
static void RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg)
Definition: tablecmds.c:13035
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:1120
#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 12520 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().

12522 {
12523  Relation classRel;
12524 
12525  Assert(objsMoved != NULL);
12526 
12527  /* OK, modify the pg_class row and pg_depend entry */
12529 
12530  AlterRelationNamespaceInternal(classRel, RelationGetRelid(rel), oldNspOid,
12531  nspOid, true, objsMoved);
12532 
12533  /* Fix the table's row type too */
12534  AlterTypeNamespaceInternal(rel->rd_rel->reltype,
12535  nspOid, false, false, objsMoved);
12536 
12537  /* Fix other dependent stuff */
12538  if (rel->rd_rel->relkind == RELKIND_RELATION ||
12539  rel->rd_rel->relkind == RELKIND_MATVIEW ||
12540  rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
12541  {
12542  AlterIndexNamespaces(classRel, rel, oldNspOid, nspOid, objsMoved);
12543  AlterSeqNamespaces(classRel, rel, oldNspOid, nspOid,
12544  objsMoved, AccessExclusiveLock);
12545  AlterConstraintNamespaces(RelationGetRelid(rel), oldNspOid, nspOid,
12546  false, objsMoved);
12547  }
12548 
12549  heap_close(classRel, RowExclusiveLock);
12550 }
#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:3506
#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:12628
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:12673
#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:1290
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:676
void AlterRelationNamespaceInternal(Relation classRel, Oid relOid, Oid oldNspOid, Oid newNspOid, bool hasDependEntry, ObjectAddresses *objsMoved)
Definition: tablecmds.c:12558
#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 12925 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().

12927 {
12928  ListCell *cur_item;
12929  ListCell *prev_item;
12930 
12931  prev_item = NULL;
12932  cur_item = list_head(on_commits);
12933 
12934  while (cur_item != NULL)
12935  {
12936  OnCommitItem *oc = (OnCommitItem *) lfirst(cur_item);
12937 
12938  if (!isCommit && oc->creating_subid == mySubid)
12939  {
12940  /* cur_item must be removed */
12941  on_commits = list_delete_cell(on_commits, cur_item, prev_item);
12942  pfree(oc);
12943  if (prev_item)
12944  cur_item = lnext(prev_item);
12945  else
12946  cur_item = list_head(on_commits);
12947  }
12948  else
12949  {
12950  /* cur_item must be preserved */
12951  if (oc->creating_subid == mySubid)
12952  oc->creating_subid = parentSubid;
12953  if (oc->deleting_subid == mySubid)
12954  oc->deleting_subid = isCommit ? parentSubid : InvalidSubTransactionId;
12955  prev_item = cur_item;
12956  cur_item = lnext(prev_item);
12957  }
12958  }
12959 }
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 12883 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().

12884 {
12885  ListCell *cur_item;
12886  ListCell *prev_item;
12887 
12888  prev_item = NULL;
12889  cur_item = list_head(on_commits);
12890 
12891  while (cur_item != NULL)
12892  {
12893  OnCommitItem *oc = (OnCommitItem *) lfirst(cur_item);
12894 
12895  if (isCommit ? oc->deleting_subid != InvalidSubTransactionId :
12897  {
12898  /* cur_item must be removed */
12899  on_commits = list_delete_cell(on_commits, cur_item, prev_item);
12900  pfree(oc);
12901  if (prev_item)
12902  cur_item = lnext(prev_item);
12903  else
12904  cur_item = list_head(on_commits);
12905  }
12906  else
12907  {
12908  /* cur_item must be preserved */
12911  prev_item = cur_item;
12912  cur_item = lnext(prev_item);
12913  }
12914  }
12915 }
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 9828 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().

9829 {
9830  Relation target_rel;
9831  Relation class_rel;
9832  HeapTuple tuple;
9833  Form_pg_class tuple_class;
9834 
9835  /*
9836  * Get exclusive lock till end of transaction on the target table. Use
9837  * relation_open so that we can work on indexes and sequences.
9838  */
9839  target_rel = relation_open(relationOid, lockmode);
9840 
9841  /* Get its pg_class tuple, too */
9843 
9844  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relationOid));
9845  if (!HeapTupleIsValid(tuple))
9846  elog(ERROR, "cache lookup failed for relation %u", relationOid);
9847  tuple_class = (Form_pg_class) GETSTRUCT(tuple);
9848 
9849  /* Can we change the ownership of this tuple? */
9850  switch (tuple_class->relkind)
9851  {
9852  case RELKIND_RELATION:
9853  case RELKIND_VIEW:
9854  case RELKIND_MATVIEW:
9855  case RELKIND_FOREIGN_TABLE:
9857  /* ok to change owner */
9858  break;
9859  case RELKIND_INDEX:
9860  if (!recursing)
9861  {
9862  /*
9863  * Because ALTER INDEX OWNER used to be allowed, and in fact
9864  * is generated by old versions of pg_dump, we give a warning
9865  * and do nothing rather than erroring out. Also, to avoid
9866  * unnecessary chatter while restoring those old dumps, say
9867  * nothing at all if the command would be a no-op anyway.
9868  */
9869  if (tuple_class->relowner != newOwnerId)
9870  ereport(WARNING,
9871  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
9872  errmsg("cannot change owner of index \"%s\"",
9873  NameStr(tuple_class->relname)),
9874  errhint("Change the ownership of the index's table, instead.")));
9875  /* quick hack to exit via the no-op path */
9876  newOwnerId = tuple_class->relowner;
9877  }
9878  break;
9879  case RELKIND_SEQUENCE:
9880  if (!recursing &&
9881  tuple_class->relowner != newOwnerId)
9882  {
9883  /* if it's an owned sequence, disallow changing it by itself */
9884  Oid tableId;
9885  int32 colId;
9886 
9887  if (sequenceIsOwned(relationOid, DEPENDENCY_AUTO, &tableId, &colId) ||
9888  sequenceIsOwned(relationOid, DEPENDENCY_INTERNAL, &tableId, &colId))
9889  ereport(ERROR,
9890  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
9891  errmsg("cannot change owner of sequence \"%s\"",
9892  NameStr(tuple_class->relname)),
9893  errdetail("Sequence \"%s\" is linked to table \"%s\".",
9894  NameStr(tuple_class->relname),
9895  get_rel_name(tableId))));
9896  }
9897  break;
9899  if (recursing)
9900  break;
9901  ereport(ERROR,
9902  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
9903  errmsg("\"%s\" is a composite type",
9904  NameStr(tuple_class->relname)),
9905  errhint("Use ALTER TYPE instead.")));
9906  break;
9907  case RELKIND_TOASTVALUE:
9908  if (recursing)
9909  break;
9910  /* FALL THRU */
9911  default:
9912  ereport(ERROR,
9913  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
9914  errmsg("\"%s\" is not a table, view, sequence, or foreign table",
9915  NameStr(tuple_class->relname))));
9916  }
9917 
9918  /*
9919  * If the new owner is the same as the existing owner, consider the
9920  * command to have succeeded. This is for dump restoration purposes.
9921  */
9922  if (tuple_class->relowner != newOwnerId)
9923  {
9924  Datum repl_val[Natts_pg_class];
9925  bool repl_null[Natts_pg_class];
9926  bool repl_repl[Natts_pg_class];
9927  Acl *newAcl;
9928  Datum aclDatum;
9929  bool isNull;
9930  HeapTuple newtuple;
9931 
9932  /* skip permission checks when recursing to index or toast table */
9933  if (!recursing)
9934  {
9935  /* Superusers can always do it */
9936  if (!superuser())
9937  {
9938  Oid namespaceOid = tuple_class->relnamespace;
9939  AclResult aclresult;
9940 
9941  /* Otherwise, must be owner of the existing object */
9942  if (!pg_class_ownercheck(relationOid, GetUserId()))
9944  RelationGetRelationName(target_rel));
9945 
9946  /* Must be able to become new owner */
9947  check_is_member_of_role(GetUserId(), newOwnerId);
9948 
9949  /* New owner must have CREATE privilege on namespace */
9950  aclresult = pg_namespace_aclcheck(namespaceOid, newOwnerId,
9951  ACL_CREATE);
9952  if (aclresult != ACLCHECK_OK)
9954  get_namespace_name(namespaceOid));
9955  }
9956  }
9957 
9958  memset(repl_null, false, sizeof(repl_null));
9959  memset(repl_repl, false, sizeof(repl_repl));
9960 
9961  repl_repl[Anum_pg_class_relowner - 1] = true;
9962  repl_val[Anum_pg_class_relowner - 1] = ObjectIdGetDatum(newOwnerId);
9963 
9964  /*
9965  * Determine the modified ACL for the new owner. This is only
9966  * necessary when the ACL is non-null.
9967  */
9968  aclDatum = SysCacheGetAttr(RELOID, tuple,
9970  &isNull);
9971  if (!isNull)
9972  {
9973  newAcl = aclnewowner(DatumGetAclP(aclDatum),
9974  tuple_class->relowner, newOwnerId);
9975  repl_repl[Anum_pg_class_relacl - 1] = true;
9976  repl_val[Anum_pg_class_relacl - 1] = PointerGetDatum(newAcl);
9977  }
9978 
9979  newtuple = heap_modify_tuple(tuple, RelationGetDescr(class_rel), repl_val, repl_null, repl_repl);
9980 
9981  CatalogTupleUpdate(class_rel, &newtuple->t_self, newtuple);
9982 
9983  heap_freetuple(newtuple);
9984 
9985  /*
9986  * We must similarly update any per-column ACLs to reflect the new
9987  * owner; for neatness reasons that's split out as a subroutine.
9988  */
9989  change_owner_fix_column_acls(relationOid,
9990  tuple_class->relowner,
9991  newOwnerId);
9992 
9993  /*
9994  * Update owner dependency reference, if any. A composite type has
9995  * none, because it's tracked for the pg_type entry instead of here;
9996  * indexes and TOAST tables don't have their own entries either.
9997  */
9998  if (tuple_class->relkind != RELKIND_COMPOSITE_TYPE &&
9999  tuple_class->relkind != RELKIND_INDEX &&
10000  tuple_class->relkind != RELKIND_TOASTVALUE)
10002  newOwnerId);
10003 
10004  /*
10005  * Also change the ownership of the table's row type, if it has one
10006  */
10007  if (tuple_class->relkind != RELKIND_INDEX)
10008  AlterTypeOwnerInternal(tuple_class->reltype, newOwnerId);
10009 
10010  /*
10011  * If we are operating on a table or materialized view, also change
10012  * the ownership of any indexes and sequences that belong to the
10013  * relation, as well as its toast table (if it has one).
10014  */
10015  if (tuple_class->relkind == RELKIND_RELATION ||
10016  tuple_class->relkind == RELKIND_MATVIEW ||
10017  tuple_class->relkind == RELKIND_TOASTVALUE)
10018  {
10019  List *index_oid_list;
10020  ListCell *i;
10021 
10022  /* Find all the indexes belonging to this relation */
10023  index_oid_list = RelationGetIndexList(target_rel);
10024 
10025  /* For each index, recursively change its ownership */
10026  foreach(i, index_oid_list)
10027  ATExecChangeOwner(lfirst_oid(i), newOwnerId, true, lockmode);
10028 
10029  list_free(index_oid_list);
10030  }
10031 
10032  if (tuple_class->relkind == RELKIND_RELATION ||
10033  tuple_class->relkind == RELKIND_MATVIEW)
10034  {
10035  /* If it has a toast table, recurse to change its ownership */
10036  if (tuple_class->reltoastrelid != InvalidOid)
10037  ATExecChangeOwner(tuple_class->reltoastrelid, newOwnerId,
10038  true, lockmode);
10039 
10040  /* If it has dependent sequences, recurse to change them too */
10041  change_owner_recurse_to_sequences(relationOid, newOwnerId, lockmode);
10042  }
10043  }
10044 
10046 
10047  ReleaseSysCache(tuple);
10048  heap_close(class_rel, RowExclusiveLock);
10049  relation_close(target_rel, NoLock);
10050 }
#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:284
#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:1266
void AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId)
Definition: typecmds.c:3376
#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:9828
#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:1290
#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:10124
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4351
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:10059
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:1120
#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 5037 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().

5038 {
5039  Form_pg_type typ = (Form_pg_type) GETSTRUCT(typetuple);
5040  bool typeOk = false;
5041 
5042  if (typ->typtype == TYPTYPE_COMPOSITE)
5043  {
5044  Relation typeRelation;
5045 
5046  Assert(OidIsValid(typ->typrelid));
5047  typeRelation = relation_open(typ->typrelid, AccessShareLock);
5048  typeOk = (typeRelation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE);
5049 
5050  /*
5051  * Close the parent rel, but keep our AccessShareLock on it until xact
5052  * commit. That will prevent someone else from deleting or ALTERing
5053  * the type before the typed table creation/conversion commits.
5054  */
5055  relation_close(typeRelation, NoLock);
5056  }
5057  if (!typeOk)
5058  ereport(ERROR,
5059  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
5060  errmsg("type %s is not a composite type",
5061  format_type_be(HeapTupleGetOid(typetuple)))));
5062 }
#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:1266
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:676
int errmsg(const char *fmt,...)
Definition: elog.c:797
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1120
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
void CheckTableNotInUse ( Relation  rel,
const char *  stmt 
)

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

3016 {
3017  int expected_refcnt;
3018 
3019  expected_refcnt = rel->rd_isnailed ? 2 : 1;
3020  if (rel->rd_refcnt != expected_refcnt)
3021  ereport(ERROR,
3022  (errcode(ERRCODE_OBJECT_IN_USE),
3023  /* translator: first %s is a SQL command, eg ALTER TABLE */
3024  errmsg("cannot %s \"%s\" because "
3025  "it is being used by active queries in this session",
3026  stmt, RelationGetRelationName(rel))));
3027 
3028  if (rel->rd_rel->relkind != RELKIND_INDEX &&
3030  ereport(ERROR,
3031  (errcode(ERRCODE_OBJECT_IN_USE),
3032  /* translator: first %s is a SQL command, eg ALTER TABLE */
3033  errmsg("cannot %s \"%s\" because "
3034  "it has pending trigger events",
3035  stmt, RelationGetRelationName(rel))));
3036 }
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:5157
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 503 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().

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

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

References AccessShareLock, Anum_pg_depend_refclassid, Anum_pg_depend_refobjid, tupleDesc::attrs, BTEqualStrategyNumber, check_stack_depth(), DependReferenceIndexId, DependRelationId, ereport, errcode(), errmsg(), ERROR, find_composite_type_dependencies(), 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().

4876 {
4877  Relation depRel;
4878  ScanKeyData key[2];
4879  SysScanDesc depScan;
4880  HeapTuple depTup;
4881 
4882  /* since this function recurses, it could be driven to stack overflow */
4884 
4885  /*
4886  * We scan pg_depend to find those things that depend on the given type.
4887  * (We assume we can ignore refobjsubid for a type.)
4888  */
4890 
4891  ScanKeyInit(&key[0],
4893  BTEqualStrategyNumber, F_OIDEQ,
4895  ScanKeyInit(&key[1],
4897  BTEqualStrategyNumber, F_OIDEQ,
4898  ObjectIdGetDatum(typeOid));
4899 
4900  depScan = systable_beginscan(depRel, DependReferenceIndexId, true,
4901  NULL, 2, key);
4902 
4903  while (HeapTupleIsValid(depTup = systable_getnext(depScan)))
4904  {
4905  Form_pg_depend pg_depend = (Form_pg_depend) GETSTRUCT(depTup);
4906  Relation rel;
4907  Form_pg_attribute att;
4908 
4909  /* Check for directly dependent types */
4910  if (pg_depend->classid == TypeRelationId)
4911  {
4912  /*
4913  * This must be an array, domain, or range containing the given
4914  * type, so recursively check for uses of this type. Note that
4915  * any error message will mention the original type not the
4916  * container; this is intentional.
4917  */
4918  find_composite_type_dependencies(pg_depend->objid,
4919  origRelation, origTypeName);
4920  continue;
4921  }
4922 
4923  /* Else, ignore dependees that aren't user columns of relations */
4924  /* (we assume system columns are never of interesting types) */
4925  if (pg_depend->classid != RelationRelationId ||
4926  pg_depend->objsubid <= 0)
4927  continue;
4928 
4929  rel = relation_open(pg_depend->objid, AccessShareLock);
4930  att = rel->rd_att->attrs[pg_depend->objsubid - 1];
4931 
4932  if (rel->rd_rel->relkind == RELKIND_RELATION ||
4933  rel->rd_rel->relkind == RELKIND_MATVIEW ||
4934  rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
4935  {
4936  if (origTypeName)
4937  ereport(ERROR,
4938  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4939  errmsg("cannot alter type \"%s\" because column \"%s.%s\" uses it",
4940  origTypeName,
4942  NameStr(att->attname))));
4943  else if (origRelation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
4944  ereport(ERROR,
4945  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4946  errmsg("cannot alter type \"%s\" because column \"%s.%s\" uses it",
4947  RelationGetRelationName(origRelation),
4949  NameStr(att->attname))));
4950  else if (origRelation->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
4951  ereport(ERROR,
4952  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4953  errmsg("cannot alter foreign table \"%s\" because column \"%s.%s\" uses its row type",
4954  RelationGetRelationName(origRelation),
4956  NameStr(att->attname))));
4957  else
4958  ereport(ERROR,
4959  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4960  errmsg("cannot alter table \"%s\" because column \"%s.%s\" uses its row type",
4961  RelationGetRelationName(origRelation),
4963  NameStr(att->attname))));
4964  }
4965  else if (OidIsValid(rel->rd_rel->reltype))
4966  {
4967  /*
4968  * A view or composite type itself isn't a problem, but we must
4969  * recursively check for indirect dependencies via its rowtype.
4970  */
4972  origRelation, origTypeName);
4973  }
4974 
4976  }
4977 
4978  systable_endscan(depScan);
4979 
4981 }
#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
#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:4874
#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:1266
Form_pg_class rd_rel
Definition: rel.h:114
#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
void check_stack_depth(void)
Definition: postgres.c:3117
#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:1290
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:1120
#define RELKIND_RELATION
Definition: pg_class.h:160
#define BTEqualStrategyNumber
Definition: stratnum.h:31
void PreCommit_on_commit_actions ( void  )

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

12813 {
12814  ListCell *l;
12815  List *oids_to_truncate = NIL;
12816 
12817  foreach(l, on_commits)
12818  {
12819  OnCommitItem *oc = (OnCommitItem *) lfirst(l);
12820 
12821  /* Ignore entry if already dropped in this xact */
12823  continue;
12824 
12825  switch (oc->oncommit)
12826  {
12827  case ONCOMMIT_NOOP:
12829  /* Do nothing (there shouldn't be such entries, actually) */
12830  break;
12831  case ONCOMMIT_DELETE_ROWS:
12832 
12833  /*
12834  * If this transaction hasn't accessed any temporary
12835  * relations, we can skip truncating ON COMMIT DELETE ROWS
12836  * tables, as they must still be empty.
12837  */
12839  oids_to_truncate = lappend_oid(oids_to_truncate, oc->relid);
12840  break;
12841  case ONCOMMIT_DROP:
12842  {
12843  ObjectAddress object;
12844 
12845  object.classId = RelationRelationId;
12846  object.objectId = oc->relid;
12847  object.objectSubId = 0;
12848 
12849  /*
12850  * Since this is an automatic drop, rather than one
12851  * directly initiated by the user, we pass the
12852  * PERFORM_DELETION_INTERNAL flag.
12853  */
12854  performDeletion(&object,
12856 
12857  /*
12858  * Note that table deletion will call
12859  * remove_on_commit_action, so the entry should get marked
12860  * as deleted.
12861  */
12863  break;
12864  }
12865  }
12866  }
12867  if (oids_to_truncate != NIL)
12868  {
12869  heap_truncate(oids_to_truncate);
12870  CommandCounterIncrement(); /* XXX needed? */
12871  }
12872 }
#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:676
#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 13003 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().

13005 {
13006  HeapTuple tuple;
13007 
13008  /* Nothing to do if the relation was not found. */
13009  if (!OidIsValid(relId))
13010  return;
13011 
13012  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relId));
13013  if (!HeapTupleIsValid(tuple)) /* should not happen */
13014  elog(ERROR, "cache lookup failed for relation %u", relId);
13015 
13016  if (!pg_class_ownercheck(relId, GetUserId()))
13018  relation->relname);
13019 
13020  if (!allowSystemTableMods &&
13021  IsSystemClass(relId, (Form_pg_class) GETSTRUCT(tuple)))
13022  ereport(ERROR,
13023  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
13024  errmsg("permission denied: \"%s\" is a system catalog",
13025  relation->relname)));
13026 
13027  ReleaseSysCache(tuple);
13028 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
Oid GetUserId(void)
Definition: miscinit.c:284
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 12970 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().

12972 {
12973  char relkind;
12974 
12975  /* Nothing to do if the relation was not found. */
12976  if (!OidIsValid(relId))
12977  return;
12978 
12979  /*
12980  * If the relation does exist, check whether it's an index. But note that
12981  * the relation might have been dropped between the time we did the name
12982  * lookup and now. In that case, there's nothing to do.
12983  */
12984  relkind = get_rel_relkind(relId);
12985  if (!relkind)
12986  return;
12987  if (relkind != RELKIND_RELATION && relkind != RELKIND_TOASTVALUE &&
12988  relkind != RELKIND_MATVIEW && relkind != RELKIND_PARTITIONED_TABLE)
12989  ereport(ERROR,
12990  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
12991  errmsg("\"%s\" is not a table or materialized view", relation->relname)));
12992 
12993  /* Check permissions */
12994  if (!pg_class_ownercheck(relId, GetUserId()))
12996 }
Oid GetUserId(void)
Definition: miscinit.c:284
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 12758 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().

12759 {
12760  OnCommitItem *oc;
12761  MemoryContext oldcxt;
12762 
12763  /*
12764  * We needn't bother registering the relation unless there is an ON COMMIT
12765  * action we need to take.
12766  */
12767  if (action == ONCOMMIT_NOOP || action == ONCOMMIT_PRESERVE_ROWS)
12768  return;
12769 
12771 
12772  oc = (OnCommitItem *) palloc(sizeof(OnCommitItem));
12773  oc->relid = relid;
12774  oc->oncommit = action;
12777 
12778  on_commits = lcons(oc, on_commits);
12779 
12780  MemoryContextSwitchTo(oldcxt);
12781 }
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 12789 of file tablecmds.c.

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

Referenced by heap_drop_with_catalog().

12790 {
12791  ListCell *l;
12792 
12793  foreach(l, on_commits)
12794  {
12795  OnCommitItem *oc = (OnCommitItem *) lfirst(l);
12796 
12797  if (oc->relid == relid)
12798  {
12800  break;
12801  }
12802  }
12803 }
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 960 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().

961 {
962  ObjectAddresses *objects;
963  char relkind;
964  ListCell *cell;
965  int flags = 0;
966  LOCKMODE lockmode = AccessExclusiveLock;
967 
968  /* DROP CONCURRENTLY uses a weaker lock, and has some restrictions */
969  if (drop->concurrent)
970  {
972  lockmode = ShareUpdateExclusiveLock;
973  Assert(drop->removeType == OBJECT_INDEX);
974  if (list_length(drop->objects) != 1)
975  ereport(ERROR,
976  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
977  errmsg("DROP INDEX CONCURRENTLY does not support dropping multiple objects")));
978  if (drop->behavior == DROP_CASCADE)
979  ereport(ERROR,
980  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
981  errmsg("DROP INDEX CONCURRENTLY does not support CASCADE")));
982  }
983 
984  /*
985  * First we identify all the relations, then we delete them in a single
986  * performMultipleDeletions() call. This is to avoid unwanted DROP
987  * RESTRICT errors if one of the relations depends on another.
988  */
989 
990  /* Determine required relkind */
991  switch (drop->removeType)
992  {
993  case OBJECT_TABLE:
994  relkind = RELKIND_RELATION;
995  break;
996 
997  case OBJECT_INDEX:
998  relkind = RELKIND_INDEX;
999  break;
1000 
1001  case OBJECT_SEQUENCE:
1002  relkind = RELKIND_SEQUENCE;
1003  break;
1004 
1005  case OBJECT_VIEW:
1006  relkind = RELKIND_VIEW;
1007  break;
1008 
1009  case OBJECT_MATVIEW:
1010  relkind = RELKIND_MATVIEW;
1011  break;
1012 
1013  case OBJECT_FOREIGN_TABLE:
1014  relkind = RELKIND_FOREIGN_TABLE;
1015  break;
1016 
1017  default:
1018  elog(ERROR, "unrecognized drop object type: %d",
1019  (int) drop->removeType);
1020  relkind = 0; /* keep compiler quiet */
1021  break;
1022  }
1023 
1024  /* Lock and validate each relation; build a list of object addresses */
1025  objects = new_object_addresses();
1026 
1027  foreach(cell, drop->objects)
1028  {
1029  RangeVar *rel = makeRangeVarFromNameList((List *) lfirst(cell));
1030  Oid relOid;
1031  ObjectAddress obj;
1033 
1034  /*
1035  * These next few steps are a great deal like relation_openrv, but we
1036  * don't bother building a relcache entry since we don't need it.
1037  *
1038  * Check for shared-cache-inval messages before trying to access the
1039  * relation. This is needed to cover the case where the name
1040  * identifies a rel that has been dropped and recreated since the
1041  * start of our transaction: if we don't flush the old syscache entry,
1042  * then we'll latch onto that entry and suffer an error later.
1043  */
1045 
1046  /* Look up the appropriate relation using namespace search. */
1047  state.relkind = relkind;
1048  state.heapOid = InvalidOid;
1049  state.partParentOid = InvalidOid;
1050  state.concurrent = drop->concurrent;
1051  relOid = RangeVarGetRelidExtended(rel, lockmode, true,
1052  false,
1054  (void *) &state);
1055 
1056  /* Not there? */
1057  if (!OidIsValid(relOid))
1058  {
1059  DropErrorMsgNonExistent(rel, relkind, drop->missing_ok);
1060  continue;
1061  }
1062 
1063  /* OK, we're ready to delete this one */
1065  obj.objectId = relOid;
1066  obj.objectSubId = 0;
1067 
1068  add_exact_object_address(&obj, objects);
1069  }
1070 
1071  performMultipleDeletions(objects, drop->behavior, flags);
1072 
1073  free_object_addresses(objects);
1074 }
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:2570
bool missing_ok
Definition: parsenodes.h:2573
#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:2571
#define PERFORM_DELETION_CONCURRENTLY
Definition: dependency.h:175
#define ERROR
Definition: elog.h:43
bool concurrent
Definition: parsenodes.h:2574
DropBehavior behavior
Definition: parsenodes.h:2572
#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:1083
#define InvalidOid
Definition: postgres_ext.h:36
#define ShareUpdateExclusiveLock
Definition: lockdefs.h:39
#define Assert(condition)
Definition: c.h:676
#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:885
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 2687 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().

2688 {
2689  Oid relid;
2690  AttrNumber attnum;
2691  ObjectAddress address;
2692 
2693  /* lock level taken here should match renameatt_internal */
2695  stmt->missing_ok, false,
2697  NULL);
2698 
2699  if (!OidIsValid(relid))
2700  {
2701  ereport(NOTICE,
2702  (errmsg("relation \"%s\" does not exist, skipping",
2703  stmt->relation->relname)));
2704  return InvalidObjectAddress;
2705  }
2706 
2707  attnum =
2708  renameatt_internal(relid,
2709  stmt->subname, /* old att name */
2710  stmt->newname, /* new att name */
2711  stmt->relation->inh, /* recursive? */
2712  false, /* recursing? */
2713  0, /* expected inhcount */
2714  stmt->behavior);
2715 
2716  ObjectAddressSubSet(address, RelationRelationId, relid, attnum);
2717 
2718  return address;
2719 }
char * subname
Definition: parsenodes.h:2798
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:2800
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:2802
#define ereport(elevel, rest)
Definition: elog.h:122
bool inh
Definition: primnodes.h:69
RangeVar * relation
Definition: parsenodes.h:2796
#define NOTICE
Definition: elog.h:37
static void RangeVarCallbackForRenameAttribute(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg)
Definition: tablecmds.c:2667
#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:2522
#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:2801
int16 AttrNumber
Definition: attnum.h:21
ObjectAddress renameatt_type ( RenameStmt stmt)
ObjectAddress RenameConstraint ( RenameStmt stmt)

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

2825 {
2826  Oid relid = InvalidOid;
2827  Oid typid = InvalidOid;
2828 
2829  if (stmt->renameType == OBJECT_DOMCONSTRAINT)
2830  {
2831  Relation rel;
2832  HeapTuple tup;
2833 
2836  tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2837  if (!HeapTupleIsValid(tup))
2838  elog(ERROR, "cache lookup failed for type %u", typid);
2839  checkDomainOwner(tup);
2840  ReleaseSysCache(tup);
2841  heap_close(rel, NoLock);
2842  }
2843  else
2844  {
2845  /* lock level taken here should match rename_constraint_internal */
2847  stmt->missing_ok, false,
2849  NULL);
2850  if (!OidIsValid(relid))
2851  {
2852  ereport(NOTICE,
2853  (errmsg("relation \"%s\" does not exist, skipping",
2854  stmt->relation->relname)));
2855  return InvalidObjectAddress;
2856  }
2857  }
2858 
2859  return
2860  rename_constraint_internal(relid, typid,
2861  stmt->subname,
2862  stmt->newname,
2863  (stmt->relation &&
2864  stmt->relation->inh), /* recursive? */
2865  false, /* recursing? */
2866  0 /* expected inhcount */ );
2867 
2868 }
char * subname
Definition: parsenodes.h:2798
ObjectType renameType
Definition: parsenodes.h:2794
#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:2725
char * newname
Definition: parsenodes.h:2800
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:2802
#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:2797
#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:1290
RangeVar * relation
Definition: parsenodes.h:2796
#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:2667
#define NULL
Definition: c.h:229
void checkDomainOwner(HeapTuple tup)
Definition: typecmds.c:2967
#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 2875 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().

2876 {
2877  Oid relid;
2878  ObjectAddress address;
2879 
2880  /*
2881  * Grab an exclusive lock on the target table, index, sequence, view,
2882  * materialized view, or foreign table, which we will NOT release until
2883  * end of transaction.
2884  *
2885  * Lock level used here should match RenameRelationInternal, to avoid lock
2886  * escalation.
2887  */
2889  stmt->missing_ok, false,
2891  (void *) stmt);
2892 
2893  if (!OidIsValid(relid))
2894  {
2895  ereport(NOTICE,
2896  (errmsg("relation \"%s\" does not exist, skipping",
2897  stmt->relation->relname)));
2898  return InvalidObjectAddress;
2899  }
2900 
2901  /* Do the work */
2902  RenameRelationInternal(relid, stmt->newname, false);
2903 
2904  ObjectAddressSet(address, RelationRelationId, relid);
2905 
2906  return address;
2907 }
void RenameRelationInternal(Oid myrelid, const char *newrelname, bool is_internal)
Definition: tablecmds.c:2919
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:2800
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:2802
static void RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg)
Definition: tablecmds.c:13035
#define ereport(elevel, rest)
Definition: elog.h:122
RangeVar * relation
Definition: parsenodes.h:2796
#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 2919 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().

2920 {
2921  Relation targetrelation;
2922  Relation relrelation; /* for RELATION relation */
2923  HeapTuple reltup;
2924  Form_pg_class relform;
2925  Oid namespaceId;
2926 
2927  /*
2928  * Grab an exclusive lock on the target table, index, sequence, view,
2929  * materialized view, or foreign table, which we will NOT release until
2930  * end of transaction.
2931  */
2932  targetrelation = relation_open(myrelid, AccessExclusiveLock);
2933  namespaceId = RelationGetNamespace(targetrelation);
2934 
2935  /*
2936  * Find relation's pg_class tuple, and make sure newrelname isn't in use.
2937  */
2939 
2940  reltup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(myrelid));
2941  if (!HeapTupleIsValid(reltup)) /* shouldn't happen */
2942  elog(ERROR, "cache lookup failed for relation %u", myrelid);
2943  relform = (Form_pg_class) GETSTRUCT(reltup);
2944 
2945  if (get_relname_relid(newrelname, namespaceId) != InvalidOid)
2946  ereport(ERROR,
2947  (errcode(ERRCODE_DUPLICATE_TABLE),
2948  errmsg("relation \"%s\" already exists",
2949  newrelname)));
2950 
2951  /*
2952  * Update pg_class tuple with new relname. (Scribbling on reltup is OK
2953  * because it's a copy...)
2954  */
2955  namestrcpy(&(relform->relname), newrelname);
2956 
2957  CatalogTupleUpdate(relrelation, &reltup->t_self, reltup);
2958 
2960  InvalidOid, is_internal);
2961 
2962  heap_freetuple(reltup);
2963  heap_close(relrelation, RowExclusiveLock);
2964 
2965  /*
2966  * Also rename the associated type, if any.
2967  */
2968  if (OidIsValid(targetrelation->rd_rel->reltype))
2969  RenameTypeInternal(targetrelation->rd_rel->reltype,
2970  newrelname, namespaceId);
2971 
2972  /*
2973  * Also rename the associated constraint, if any.
2974  */
2975  if (targetrelation->rd_rel->relkind == RELKIND_INDEX)
2976  {
2977  Oid constraintId = get_index_constraint(myrelid);
2978 
2979  if (OidIsValid(constraintId))
2980  RenameConstraintById(constraintId, newrelname);
2981  }
2982 
2983  /*
2984  * Close rel, but keep exclusive lock!
2985  */
2986  relation_close(targetrelation, NoLock);
2987 }
#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:1266
#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:1290
#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:1120
#define elog
Definition: elog.h:219
#define RelationGetNamespace(relation)
Definition: rel.h:443
void SetRelationHasSubclass ( Oid  relationId,
bool  relhassubclass 
)

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

2442 {
2443  Relation relationRelation;
2444  HeapTuple tuple;
2445  Form_pg_class classtuple;
2446 
2447  /*
2448  * Fetch a modifiable copy of the tuple, modify it, update pg_class.
2449  */
2450  relationRelation = heap_open(RelationRelationId, RowExclusiveLock);
2451  tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relationId));
2452  if (!HeapTupleIsValid(tuple))
2453  elog(ERROR, "cache lookup failed for relation %u", relationId);
2454  classtuple = (Form_pg_class) GETSTRUCT(tuple);
2455 
2456  if (classtuple->relhassubclass != relhassubclass)
2457  {
2458  classtuple->relhassubclass = relhassubclass;
2459  CatalogTupleUpdate(relationRelation, &tuple->t_self, tuple);
2460  }
2461  else
2462  {
2463  /* no need to change tuple, but force relcache rebuild anyway */
2465  }
2466 
2467  heap_freetuple(tuple);
2468  heap_close(relationRelation, RowExclusiveLock);
2469 }
#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:1290
#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