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

12177 {
12178  HeapTuple classTup;
12179  Form_pg_class classForm;
12180  ObjectAddress thisobj;
12181  bool already_done = false;
12182 
12183  classTup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relOid));
12184  if (!HeapTupleIsValid(classTup))
12185  elog(ERROR, "cache lookup failed for relation %u", relOid);
12186  classForm = (Form_pg_class) GETSTRUCT(classTup);
12187 
12188  Assert(classForm->relnamespace == oldNspOid);
12189 
12190  thisobj.classId = RelationRelationId;
12191  thisobj.objectId = relOid;
12192  thisobj.objectSubId = 0;
12193 
12194  /*
12195  * If the object has already been moved, don't move it again. If it's
12196  * already in the right place, don't move it, but still fire the object
12197  * access hook.
12198  */
12199  already_done = object_address_present(&thisobj, objsMoved);
12200  if (!already_done && oldNspOid != newNspOid)
12201  {
12202  /* check for duplicate name (more friendly than unique-index failure) */
12203  if (get_relname_relid(NameStr(classForm->relname),
12204  newNspOid) != InvalidOid)
12205  ereport(ERROR,
12206  (errcode(ERRCODE_DUPLICATE_TABLE),
12207  errmsg("relation \"%s\" already exists in schema \"%s\"",
12208  NameStr(classForm->relname),
12209  get_namespace_name(newNspOid))));
12210 
12211  /* classTup is a copy, so OK to scribble on */
12212  classForm->relnamespace = newNspOid;
12213 
12214  CatalogTupleUpdate(classRel, &classTup->t_self, classTup);
12215 
12216  /* Update dependency on schema if caller said so */
12217  if (hasDependEntry &&
12219  relOid,
12221  oldNspOid,
12222  newNspOid) != 1)
12223  elog(ERROR, "failed to change schema dependency for relation \"%s\"",
12224  NameStr(classForm->relname));
12225  }
12226  if (!already_done)
12227  {
12228  add_exact_object_address(&thisobj, objsMoved);
12229 
12231  }
12232 
12233  heap_freetuple(classTup);
12234 }
#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:2141
int errcode(int sqlerrcode)
Definition: elog.c:575
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2081
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1374
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
Oid get_relname_relid(const char *relname, Oid relnamespace)
Definition: lsyscache.c:1651
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3006
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:671
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:158
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:495
#define elog
Definition: elog.h:219
void AlterTable ( Oid  relid,
LOCKMODE  lockmode,
AlterTableStmt stmt 
)

Definition at line 3029 of file tablecmds.c.

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

Referenced by ProcessUtilitySlow().

3030 {
3031  Relation rel;
3032 
3033  /* Caller is required to provide an adequate lock. */
3034  rel = relation_open(relid, NoLock);
3035 
3036  CheckTableNotInUse(rel, "ALTER TABLE");
3037 
3038  ATController(stmt, rel, stmt->cmds, stmt->relation->inh, lockmode);
3039 }
static void ATController(AlterTableStmt *parsetree, Relation rel, List *cmds, bool recurse, LOCKMODE lockmode)
Definition: tablecmds.c:3344
#define NoLock
Definition: lockdefs.h:34
void CheckTableNotInUse(Relation rel, const char *stmt)
Definition: tablecmds.c:2950
bool inh
Definition: primnodes.h:68
RangeVar * relation
Definition: parsenodes.h:1601
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1117
LOCKMODE AlterTableGetLockLevel ( List cmds)

Definition at line 3098 of file tablecmds.c.

References AccessExclusiveLock, AlterTableGetRelOptionsLockLevel(), AT_AddColumn, AT_AddColumnToView, AT_AddConstraint, AT_AddConstraintRecurse, AT_AddIndex, AT_AddIndexConstraint, AT_AddInherit, AT_AddOf, AT_AddOids, AT_AlterColumnGenericOptions, AT_AlterColumnType, AT_AlterConstraint, AT_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_DropInherit, AT_DropNotNull, AT_DropOf, AT_DropOids, AT_EnableAlwaysRule, AT_EnableAlwaysTrig, AT_EnableReplicaRule, AT_EnableReplicaTrig, AT_EnableRowSecurity, AT_EnableRule, AT_EnableTrig, AT_EnableTrigAll, AT_EnableTrigUser, AT_ForceRowSecurity, AT_GenericOptions, AT_NoForceRowSecurity, AT_ProcessedConstraint, AT_ReAddConstraint, AT_ReplaceRelOptions, AT_ReplicaIdentity, AT_ResetOptions, AT_ResetRelOptions, AT_SetLogged, AT_SetNotNull, AT_SetOptions, AT_SetRelOptions, AT_SetStatistics, AT_SetStorage, AT_SetTableSpace, AT_SetUnLogged, AT_ValidateConstraint, CONSTR_EXCLUSION, CONSTR_FOREIGN, CONSTR_PRIMARY, CONSTR_UNIQUE, Constraint::contype, AlterTableCmd::def, elog, ERROR, IsA, lfirst, ShareRowExclusiveLock, ShareUpdateExclusiveLock, and AlterTableCmd::subtype.

Referenced by AlterTableInternal(), and ProcessUtilitySlow().

3099 {
3100  /*
3101  * This only works if we read catalog tables using MVCC snapshots.
3102  */
3103  ListCell *lcmd;
3105 
3106  foreach(lcmd, cmds)
3107  {
3108  AlterTableCmd *cmd = (AlterTableCmd *) lfirst(lcmd);
3109  LOCKMODE cmd_lockmode = AccessExclusiveLock; /* default for compiler */
3110 
3111  switch (cmd->subtype)
3112  {
3113  /*
3114  * These subcommands rewrite the heap, so require full locks.
3115  */
3116  case AT_AddColumn: /* may rewrite heap, in some cases and visible
3117  * to SELECT */
3118  case AT_SetTableSpace: /* must rewrite heap */
3119  case AT_AlterColumnType: /* must rewrite heap */
3120  case AT_AddOids: /* must rewrite heap */
3121  cmd_lockmode = AccessExclusiveLock;
3122  break;
3123 
3124  /*
3125  * These subcommands may require addition of toast tables. If
3126  * we add a toast table to a table currently being scanned, we
3127  * might miss data added to the new toast table by concurrent
3128  * insert transactions.
3129  */
3130  case AT_SetStorage:/* may add toast tables, see
3131  * ATRewriteCatalogs() */
3132  cmd_lockmode = AccessExclusiveLock;
3133  break;
3134 
3135  /*
3136  * Removing constraints can affect SELECTs that have been
3137  * optimised assuming the constraint holds true.
3138  */
3139  case AT_DropConstraint: /* as DROP INDEX */
3140  case AT_DropNotNull: /* may change some SQL plans */
3141  cmd_lockmode = AccessExclusiveLock;
3142  break;
3143 
3144  /*
3145  * Subcommands that may be visible to concurrent SELECTs
3146  */
3147  case AT_DropColumn: /* change visible to SELECT */
3148  case AT_AddColumnToView: /* CREATE VIEW */
3149  case AT_DropOids: /* calls AT_DropColumn */
3150  case AT_EnableAlwaysRule: /* may change SELECT rules */
3151  case AT_EnableReplicaRule: /* may change SELECT rules */
3152  case AT_EnableRule: /* may change SELECT rules */
3153  case AT_DisableRule: /* may change SELECT rules */
3154  cmd_lockmode = AccessExclusiveLock;
3155  break;
3156 
3157  /*
3158  * Changing owner may remove implicit SELECT privileges
3159  */
3160  case AT_ChangeOwner: /* change visible to SELECT */
3161  cmd_lockmode = AccessExclusiveLock;
3162  break;
3163 
3164  /*
3165  * Changing foreign table options may affect optimisation.
3166  */
3167  case AT_GenericOptions:
3169  cmd_lockmode = AccessExclusiveLock;
3170  break;
3171 
3172  /*
3173  * These subcommands affect write operations only.
3174  */
3175  case AT_EnableTrig:
3176  case AT_EnableAlwaysTrig:
3177  case AT_EnableReplicaTrig:
3178  case AT_EnableTrigAll:
3179  case AT_EnableTrigUser:
3180  case AT_DisableTrig:
3181  case AT_DisableTrigAll:
3182  case AT_DisableTrigUser:
3183  cmd_lockmode = ShareRowExclusiveLock;
3184  break;
3185 
3186  /*
3187  * These subcommands affect write operations only. XXX
3188  * Theoretically, these could be ShareRowExclusiveLock.
3189  */
3190  case AT_ColumnDefault:
3191  case AT_AlterConstraint:
3192  case AT_AddIndex: /* from ADD CONSTRAINT */
3193  case AT_AddIndexConstraint:
3194  case AT_ReplicaIdentity:
3195  case AT_SetNotNull:
3196  case AT_EnableRowSecurity:
3197  case AT_DisableRowSecurity:
3198  case AT_ForceRowSecurity:
3199  case AT_NoForceRowSecurity:
3200  cmd_lockmode = AccessExclusiveLock;
3201  break;
3202 
3203  case AT_AddConstraint:
3204  case AT_ProcessedConstraint: /* becomes AT_AddConstraint */
3205  case AT_AddConstraintRecurse: /* becomes AT_AddConstraint */
3206  case AT_ReAddConstraint: /* becomes AT_AddConstraint */
3207  if (IsA(cmd->def, Constraint))
3208  {
3209  Constraint *con = (Constraint *) cmd->def;
3210 
3211  switch (con->contype)
3212  {
3213  case CONSTR_EXCLUSION:
3214  case CONSTR_PRIMARY:
3215  case CONSTR_UNIQUE:
3216 
3217  /*
3218  * Cases essentially the same as CREATE INDEX. We
3219  * could reduce the lock strength to ShareLock if
3220  * we can work out how to allow concurrent catalog
3221  * updates. XXX Might be set down to
3222  * ShareRowExclusiveLock but requires further
3223  * analysis.
3224  */
3225  cmd_lockmode = AccessExclusiveLock;
3226  break;
3227  case CONSTR_FOREIGN:
3228 
3229  /*
3230  * We add triggers to both tables when we add a
3231  * Foreign Key, so the lock level must be at least
3232  * as strong as CREATE TRIGGER.
3233  */
3234  cmd_lockmode = ShareRowExclusiveLock;
3235  break;
3236 
3237  default:
3238  cmd_lockmode = AccessExclusiveLock;
3239  }
3240  }
3241  break;
3242 
3243  /*
3244  * These subcommands affect inheritance behaviour. Queries
3245  * started before us will continue to see the old inheritance
3246  * behaviour, while queries started after we commit will see
3247  * new behaviour. No need to prevent reads or writes to the
3248  * subtable while we hook it up though. Changing the TupDesc
3249  * may be a problem, so keep highest lock.
3250  */
3251  case AT_AddInherit:
3252  case AT_DropInherit:
3253  cmd_lockmode = AccessExclusiveLock;
3254  break;
3255 
3256  /*
3257  * These subcommands affect implicit row type conversion. They
3258  * have affects similar to CREATE/DROP CAST on queries. don't
3259  * provide for invalidating parse trees as a result of such
3260  * changes, so we keep these at AccessExclusiveLock.
3261  */
3262  case AT_AddOf:
3263  case AT_DropOf:
3264  cmd_lockmode = AccessExclusiveLock;
3265  break;
3266 
3267  /*
3268  * Only used by CREATE OR REPLACE VIEW which must conflict
3269  * with an SELECTs currently using the view.
3270  */
3271  case AT_ReplaceRelOptions:
3272  cmd_lockmode = AccessExclusiveLock;
3273  break;
3274 
3275  /*
3276  * These subcommands affect general strategies for performance
3277  * and maintenance, though don't change the semantic results
3278  * from normal data reads and writes. Delaying an ALTER TABLE
3279  * behind currently active writes only delays the point where
3280  * the new strategy begins to take effect, so there is no
3281  * benefit in waiting. In this case the minimum restriction
3282  * applies: we don't currently allow concurrent catalog
3283  * updates.
3284  */
3285  case AT_SetStatistics: /* Uses MVCC in getTableAttrs() */
3286  case AT_ClusterOn: /* Uses MVCC in getIndexes() */
3287  case AT_DropCluster: /* Uses MVCC in getIndexes() */
3288  case AT_SetOptions: /* Uses MVCC in getTableAttrs() */
3289  case AT_ResetOptions: /* Uses MVCC in getTableAttrs() */
3290  cmd_lockmode = ShareUpdateExclusiveLock;
3291  break;
3292 
3293  case AT_SetLogged:
3294  case AT_SetUnLogged:
3295  cmd_lockmode = AccessExclusiveLock;
3296  break;
3297 
3298  case AT_ValidateConstraint: /* Uses MVCC in
3299  * getConstraints() */
3300  cmd_lockmode = ShareUpdateExclusiveLock;
3301  break;
3302 
3303  /*
3304  * Rel options are more complex than first appears. Options
3305  * are set here for tables, views and indexes; for historical
3306  * reasons these can all be used with ALTER TABLE, so we can't
3307  * decide between them using the basic grammar.
3308  */
3309  case AT_SetRelOptions: /* Uses MVCC in getIndexes() and
3310  * getTables() */
3311  case AT_ResetRelOptions: /* Uses MVCC in getIndexes() and
3312  * getTables() */
3313  cmd_lockmode = AlterTableGetRelOptionsLockLevel((List *) cmd->def);
3314  break;
3315 
3316  case AT_AttachPartition:
3317  case AT_DetachPartition:
3318  cmd_lockmode = AccessExclusiveLock;
3319  break;
3320 
3321  default: /* oops */
3322  elog(ERROR, "unrecognized alter table type: %d",
3323  (int) cmd->subtype);
3324  break;
3325  }
3326 
3327  /*
3328  * Take the greatest lockmode from any subcommand
3329  */
3330  if (cmd_lockmode > lockmode)
3331  lockmode = cmd_lockmode;
3332  }
3333 
3334  return lockmode;
3335 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
int LOCKMODE
Definition: lockdefs.h:26
AlterTableType subtype
Definition: parsenodes.h:1685
#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:1485
#define AccessExclusiveLock
Definition: lockdefs.h:46
ConstrType contype
Definition: parsenodes.h:1971
#define elog
Definition: elog.h:219
Definition: pg_list.h:45
void AlterTableInternal ( Oid  relid,
List cmds,
bool  recurse 
)

Definition at line 3053 of file tablecmds.c.

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

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

3054 {
3055  Relation rel;
3056  LOCKMODE lockmode = AlterTableGetLockLevel(cmds);
3057 
3058  rel = relation_open(relid, lockmode);
3059 
3061 
3062  ATController(NULL, rel, cmds, recurse, lockmode);
3063 }
int LOCKMODE
Definition: lockdefs.h:26
static void ATController(AlterTableStmt *parsetree, Relation rel, List *cmds, bool recurse, LOCKMODE lockmode)
Definition: tablecmds.c:3344
LOCKMODE AlterTableGetLockLevel(List *cmds)
Definition: tablecmds.c:3098
#define NULL
Definition: c.h:226
void EventTriggerAlterTableRelid(Oid objectId)
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1117
Oid AlterTableLookupRelation ( AlterTableStmt stmt,
LOCKMODE  lockmode 
)

Definition at line 2979 of file tablecmds.c.

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

Referenced by ProcessUtilitySlow().

2980 {
2981  return RangeVarGetRelidExtended(stmt->relation, lockmode, stmt->missing_ok, false,
2983  (void *) stmt);
2984 }
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, bool missing_ok, bool nowait, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:217
static void RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg)
Definition: tablecmds.c:12650
RangeVar * relation
Definition: parsenodes.h:1601
Oid AlterTableMoveAll ( AlterTableMoveAllStmt stmt)

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

10276 {
10277  List *relations = NIL;
10278  ListCell *l;
10279  ScanKeyData key[1];
10280  Relation rel;
10281  HeapScanDesc scan;
10282  HeapTuple tuple;
10283  Oid orig_tablespaceoid;
10284  Oid new_tablespaceoid;
10285  List *role_oids = roleSpecsToIds(stmt->roles);
10286 
10287  /* Ensure we were not asked to move something we can't */
10288  if (stmt->objtype != OBJECT_TABLE && stmt->objtype != OBJECT_INDEX &&
10289  stmt->objtype != OBJECT_MATVIEW)
10290  ereport(ERROR,
10291  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
10292  errmsg("only tables, indexes, and materialized views exist in tablespaces")));
10293 
10294  /* Get the orig and new tablespace OIDs */
10295  orig_tablespaceoid = get_tablespace_oid(stmt->orig_tablespacename, false);
10296  new_tablespaceoid = get_tablespace_oid(stmt->new_tablespacename, false);
10297 
10298  /* Can't move shared relations in to or out of pg_global */
10299  /* This is also checked by ATExecSetTableSpace, but nice to stop earlier */
10300  if (orig_tablespaceoid == GLOBALTABLESPACE_OID ||
10301  new_tablespaceoid == GLOBALTABLESPACE_OID)
10302  ereport(ERROR,
10303  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
10304  errmsg("cannot move relations in to or out of pg_global tablespace")));
10305 
10306  /*
10307  * Must have CREATE rights on the new tablespace, unless it is the
10308  * database default tablespace (which all users implicitly have CREATE
10309  * rights on).
10310  */
10311  if (OidIsValid(new_tablespaceoid) && new_tablespaceoid != MyDatabaseTableSpace)
10312  {
10313  AclResult aclresult;
10314 
10315  aclresult = pg_tablespace_aclcheck(new_tablespaceoid, GetUserId(),
10316  ACL_CREATE);
10317  if (aclresult != ACLCHECK_OK)
10319  get_tablespace_name(new_tablespaceoid));
10320  }
10321 
10322  /*
10323  * Now that the checks are done, check if we should set either to
10324  * InvalidOid because it is our database's default tablespace.
10325  */
10326  if (orig_tablespaceoid == MyDatabaseTableSpace)
10327  orig_tablespaceoid = InvalidOid;
10328 
10329  if (new_tablespaceoid == MyDatabaseTableSpace)
10330  new_tablespaceoid = InvalidOid;
10331 
10332  /* no-op */
10333  if (orig_tablespaceoid == new_tablespaceoid)
10334  return new_tablespaceoid;
10335 
10336  /*
10337  * Walk the list of objects in the tablespace and move them. This will
10338  * only find objects in our database, of course.
10339  */
10340  ScanKeyInit(&key[0],
10342  BTEqualStrategyNumber, F_OIDEQ,
10343  ObjectIdGetDatum(orig_tablespaceoid));
10344 
10346  scan = heap_beginscan_catalog(rel, 1, key);
10347  while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
10348  {
10349  Oid relOid = HeapTupleGetOid(tuple);
10350  Form_pg_class relForm;
10351 
10352  relForm = (Form_pg_class) GETSTRUCT(tuple);
10353 
10354  /*
10355  * Do not move objects in pg_catalog as part of this, if an admin
10356  * really wishes to do so, they can issue the individual ALTER
10357  * commands directly.
10358  *
10359  * Also, explicitly avoid any shared tables, temp tables, or TOAST
10360  * (TOAST will be moved with the main table).
10361  */
10362  if (IsSystemNamespace(relForm->relnamespace) || relForm->relisshared ||
10363  isAnyTempNamespace(relForm->relnamespace) ||
10364  relForm->relnamespace == PG_TOAST_NAMESPACE)
10365  continue;
10366 
10367  /* Only move the object type requested */
10368  if ((stmt->objtype == OBJECT_TABLE &&
10369  relForm->relkind != RELKIND_RELATION &&
10370  relForm->relkind != RELKIND_PARTITIONED_TABLE) ||
10371  (stmt->objtype == OBJECT_INDEX &&
10372  relForm->relkind != RELKIND_INDEX) ||
10373  (stmt->objtype == OBJECT_MATVIEW &&
10374  relForm->relkind != RELKIND_MATVIEW))
10375  continue;
10376 
10377  /* Check if we are only moving objects owned by certain roles */
10378  if (role_oids != NIL && !list_member_oid(role_oids, relForm->relowner))
10379  continue;
10380 
10381  /*
10382  * Handle permissions-checking here since we are locking the tables
10383  * and also to avoid doing a bunch of work only to fail part-way. Note
10384  * that permissions will also be checked by AlterTableInternal().
10385  *
10386  * Caller must be considered an owner on the table to move it.
10387  */
10388  if (!pg_class_ownercheck(relOid, GetUserId()))
10390  NameStr(relForm->relname));
10391 
10392  if (stmt->nowait &&
10394  ereport(ERROR,
10395  (errcode(ERRCODE_OBJECT_IN_USE),
10396  errmsg("aborting because lock on relation \"%s.%s\" is not available",
10397  get_namespace_name(relForm->relnamespace),
10398  NameStr(relForm->relname))));
10399  else
10401 
10402  /* Add to our list of objects to move */
10403  relations = lappend_oid(relations, relOid);
10404  }
10405 
10406  heap_endscan(scan);
10408 
10409  if (relations == NIL)
10410  ereport(NOTICE,
10411  (errcode(ERRCODE_NO_DATA_FOUND),
10412  errmsg("no matching relations in tablespace \"%s\" found",
10413  orig_tablespaceoid == InvalidOid ? "(database default)" :
10414  get_tablespace_name(orig_tablespaceoid))));
10415 
10416  /* Everything is locked, loop through and move all of the relations. */
10417  foreach(l, relations)
10418  {
10419  List *cmds = NIL;
10421 
10422  cmd->subtype = AT_SetTableSpace;
10423  cmd->name = stmt->new_tablespacename;
10424 
10425  cmds = lappend(cmds, cmd);
10426 
10428  /* OID is set by AlterTableInternal */
10429  AlterTableInternal(lfirst_oid(l), cmds, false);
10431  }
10432 
10433  return new_tablespaceoid;
10434 }
#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:4471
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
void heap_endscan(HeapScanDesc scan)
Definition: heapam.c:1581
Oid GetUserId(void)
Definition: miscinit.c:282
#define RelationRelationId
Definition: pg_class.h:29
#define Anum_pg_class_reltablespace
Definition: pg_class.h:110
#define RELKIND_MATVIEW
Definition: pg_class.h:167
#define AccessShareLock
Definition: lockdefs.h:36
#define GLOBALTABLESPACE_OID
Definition: pg_tablespace.h:64
Definition: nodes.h:508
int errcode(int sqlerrcode)
Definition: elog.c:575
AlterTableType subtype
Definition: parsenodes.h:1685
#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:534
Oid MyDatabaseTableSpace
Definition: globals.c:78
void EventTriggerAlterTableStart(Node *parsetree)
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
#define ACL_CREATE
Definition: parsenodes.h:75
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3006
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3378
HeapScanDesc heap_beginscan_catalog(Relation relation, int nkeys, ScanKey key)
Definition: heapam.c:1402
#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:1781
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
bool IsSystemNamespace(Oid namespaceId)
Definition: catalog.c:162
#define InvalidOid
Definition: postgres_ext.h:36
#define NOTICE
Definition: elog.h:37
#define makeNode(_type_)
Definition: nodes.h:556
List * roleSpecsToIds(List *memberNames)
Definition: user.c:1374
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:505
#define NULL
Definition: c.h:226
bool pg_class_ownercheck(Oid class_oid, Oid roleid)
Definition: aclchk.c:4521
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
void AlterTableInternal(Oid relid, List *cmds, bool recurse)
Definition: tablecmds.c:3053
#define AccessExclusiveLock
Definition: lockdefs.h:46
int errmsg(const char *fmt,...)
Definition: elog.c:797
char * get_tablespace_name(Oid spc_oid)
Definition: tablespace.c:1426
#define NameStr(name)
Definition: c.h:495
#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:2990
#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 12065 of file tablecmds.c.

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

Referenced by ExecAlterObjectSchemaStmt().

12066 {
12067  Relation rel;
12068  Oid relid;
12069  Oid oldNspOid;
12070  Oid nspOid;
12071  RangeVar *newrv;
12072  ObjectAddresses *objsMoved;
12073  ObjectAddress myself;
12074 
12076  stmt->missing_ok, false,
12078  (void *) stmt);
12079 
12080  if (!OidIsValid(relid))
12081  {
12082  ereport(NOTICE,
12083  (errmsg("relation \"%s\" does not exist, skipping",
12084  stmt->relation->relname)));
12085  return InvalidObjectAddress;
12086  }
12087 
12088  rel = relation_open(relid, NoLock);
12089 
12090  oldNspOid = RelationGetNamespace(rel);
12091 
12092  /* If it's an owned sequence, disallow moving it by itself. */
12093  if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
12094  {
12095  Oid tableId;
12096  int32 colId;
12097 
12098  if (sequenceIsOwned(relid, &tableId, &colId))
12099  ereport(ERROR,
12100  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
12101  errmsg("cannot move an owned sequence into another schema"),
12102  errdetail("Sequence \"%s\" is linked to table \"%s\".",
12104  get_rel_name(tableId))));
12105  }
12106 
12107  /* Get and lock schema OID and check its permissions. */
12108  newrv = makeRangeVar(stmt->newschema, RelationGetRelationName(rel), -1);
12110 
12111  /* common checks on switching namespaces */
12112  CheckSetNamespace(oldNspOid, nspOid);
12113 
12114  objsMoved = new_object_addresses();
12115  AlterTableNamespaceInternal(rel, oldNspOid, nspOid, objsMoved);
12116  free_object_addresses(objsMoved);
12117 
12118  ObjectAddressSet(myself, RelationRelationId, relid);
12119 
12120  if (oldschema)
12121  *oldschema = oldNspOid;
12122 
12123  /* close rel, but keep lock until commit */
12124  relation_close(rel, NoLock);
12125 
12126  return myself;
12127 }
bool sequenceIsOwned(Oid seqId, 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:217
#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:1263
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2026
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2297
Form_pg_class rd_rel
Definition: rel.h:113
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:534
signed int int32
Definition: c.h:253
char * relname
Definition: primnodes.h:67
#define ERROR
Definition: elog.h:43
void AlterTableNamespaceInternal(Relation rel, Oid oldNspOid, Oid nspOid, ObjectAddresses *objsMoved)
Definition: tablecmds.c:12135
#define NoLock
Definition: lockdefs.h:34
static void RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg)
Definition: tablecmds.c:12650
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define RelationGetRelationName(relation)
Definition: rel.h:433
#define ereport(elevel, rest)
Definition: elog.h:122
void CheckSetNamespace(Oid oldNspOid, Oid nspOid)
Definition: namespace.c:2762
Oid RangeVarGetAndCheckCreationNamespace(RangeVar *relation, LOCKMODE lockmode, Oid *existing_relation_id)
Definition: namespace.c:507
#define NOTICE
Definition: elog.h:37
#define NULL
Definition: c.h:226
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define AccessExclusiveLock
Definition: lockdefs.h:46
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:797
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1117
#define RELKIND_SEQUENCE
Definition: pg_class.h:162
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1694
RangeVar * makeRangeVar(char *schemaname, char *relname, int location)
Definition: makefuncs.c:419
#define RelationGetNamespace(relation)
Definition: rel.h:440
void AlterTableNamespaceInternal ( Relation  rel,
Oid  oldNspOid,
Oid  nspOid,
ObjectAddresses objsMoved 
)

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

12137 {
12138  Relation classRel;
12139 
12140  Assert(objsMoved != NULL);
12141 
12142  /* OK, modify the pg_class row and pg_depend entry */
12144 
12145  AlterRelationNamespaceInternal(classRel, RelationGetRelid(rel), oldNspOid,
12146  nspOid, true, objsMoved);
12147 
12148  /* Fix the table's row type too */
12149  AlterTypeNamespaceInternal(rel->rd_rel->reltype,
12150  nspOid, false, false, objsMoved);
12151 
12152  /* Fix other dependent stuff */
12153  if (rel->rd_rel->relkind == RELKIND_RELATION ||
12154  rel->rd_rel->relkind == RELKIND_MATVIEW ||
12155  rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
12156  {
12157  AlterIndexNamespaces(classRel, rel, oldNspOid, nspOid, objsMoved);
12158  AlterSeqNamespaces(classRel, rel, oldNspOid, nspOid,
12159  objsMoved, AccessExclusiveLock);
12160  AlterConstraintNamespaces(RelationGetRelid(rel), oldNspOid, nspOid,
12161  false, objsMoved);
12162  }
12163 
12164  heap_close(classRel, RowExclusiveLock);
12165 }
#define RelationRelationId
Definition: pg_class.h:29
#define RELKIND_MATVIEW
Definition: pg_class.h:167
Oid AlterTypeNamespaceInternal(Oid typeOid, Oid nspOid, bool isImplicitArray, bool errorOnTableType, ObjectAddresses *objsMoved)
Definition: typecmds.c:3491
#define heap_close(r, l)
Definition: heapam.h:97
Form_pg_class rd_rel
Definition: rel.h:113
static void AlterIndexNamespaces(Relation classRel, Relation rel, Oid oldNspOid, Oid newNspOid, ObjectAddresses *objsMoved)
Definition: tablecmds.c:12243
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:12288
#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:1287
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
void AlterRelationNamespaceInternal(Relation classRel, Oid relOid, Oid oldNspOid, Oid newNspOid, bool hasDependEntry, ObjectAddresses *objsMoved)
Definition: tablecmds.c:12173
#define AccessExclusiveLock
Definition: lockdefs.h:46
#define RELKIND_RELATION
Definition: pg_class.h:160
#define RelationGetRelid(relation)
Definition: rel.h:413
void AtEOSubXact_on_commit_actions ( bool  isCommit,
SubTransactionId  mySubid,
SubTransactionId  parentSubid 
)

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

12542 {
12543  ListCell *cur_item;
12544  ListCell *prev_item;
12545 
12546  prev_item = NULL;
12547  cur_item = list_head(on_commits);
12548 
12549  while (cur_item != NULL)
12550  {
12551  OnCommitItem *oc = (OnCommitItem *) lfirst(cur_item);
12552 
12553  if (!isCommit && oc->creating_subid == mySubid)
12554  {
12555  /* cur_item must be removed */
12556  on_commits = list_delete_cell(on_commits, cur_item, prev_item);
12557  pfree(oc);
12558  if (prev_item)
12559  cur_item = lnext(prev_item);
12560  else
12561  cur_item = list_head(on_commits);
12562  }
12563  else
12564  {
12565  /* cur_item must be preserved */
12566  if (oc->creating_subid == mySubid)
12567  oc->creating_subid = parentSubid;
12568  if (oc->deleting_subid == mySubid)
12569  oc->deleting_subid = isCommit ? parentSubid : InvalidSubTransactionId;
12570  prev_item = cur_item;
12571  cur_item = lnext(prev_item);
12572  }
12573  }
12574 }
SubTransactionId creating_subid
Definition: tablecmds.c:120
void pfree(void *pointer)
Definition: mcxt.c:992
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:226
#define lfirst(lc)
Definition: pg_list.h:106
#define InvalidSubTransactionId
Definition: c.h:400
void AtEOXact_on_commit_actions ( bool  isCommit)

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

12499 {
12500  ListCell *cur_item;
12501  ListCell *prev_item;
12502 
12503  prev_item = NULL;
12504  cur_item = list_head(on_commits);
12505 
12506  while (cur_item != NULL)
12507  {
12508  OnCommitItem *oc = (OnCommitItem *) lfirst(cur_item);
12509 
12510  if (isCommit ? oc->deleting_subid != InvalidSubTransactionId :
12512  {
12513  /* cur_item must be removed */
12514  on_commits = list_delete_cell(on_commits, cur_item, prev_item);
12515  pfree(oc);
12516  if (prev_item)
12517  cur_item = lnext(prev_item);
12518  else
12519  cur_item = list_head(on_commits);
12520  }
12521  else
12522  {
12523  /* cur_item must be preserved */
12526  prev_item = cur_item;
12527  cur_item = lnext(prev_item);
12528  }
12529  }
12530 }
SubTransactionId creating_subid
Definition: tablecmds.c:120
void pfree(void *pointer)
Definition: mcxt.c:992
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:226
#define lfirst(lc)
Definition: pg_list.h:106
#define InvalidSubTransactionId
Definition: c.h:400
void ATExecChangeOwner ( Oid  relationOid,
Oid  newOwnerId,
bool  recursing,
LOCKMODE  lockmode 
)

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

9466 {
9467  Relation target_rel;
9468  Relation class_rel;
9469  HeapTuple tuple;
9470  Form_pg_class tuple_class;
9471 
9472  /*
9473  * Get exclusive lock till end of transaction on the target table. Use
9474  * relation_open so that we can work on indexes and sequences.
9475  */
9476  target_rel = relation_open(relationOid, lockmode);
9477 
9478  /* Get its pg_class tuple, too */
9480 
9481  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relationOid));
9482  if (!HeapTupleIsValid(tuple))
9483  elog(ERROR, "cache lookup failed for relation %u", relationOid);
9484  tuple_class = (Form_pg_class) GETSTRUCT(tuple);
9485 
9486  /* Can we change the ownership of this tuple? */
9487  switch (tuple_class->relkind)
9488  {
9489  case RELKIND_RELATION:
9490  case RELKIND_VIEW:
9491  case RELKIND_MATVIEW:
9492  case RELKIND_FOREIGN_TABLE:
9494  /* ok to change owner */
9495  break;
9496  case RELKIND_INDEX:
9497  if (!recursing)
9498  {
9499  /*
9500  * Because ALTER INDEX OWNER used to be allowed, and in fact
9501  * is generated by old versions of pg_dump, we give a warning
9502  * and do nothing rather than erroring out. Also, to avoid
9503  * unnecessary chatter while restoring those old dumps, say
9504  * nothing at all if the command would be a no-op anyway.
9505  */
9506  if (tuple_class->relowner != newOwnerId)
9507  ereport(WARNING,
9508  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
9509  errmsg("cannot change owner of index \"%s\"",
9510  NameStr(tuple_class->relname)),
9511  errhint("Change the ownership of the index's table, instead.")));
9512  /* quick hack to exit via the no-op path */
9513  newOwnerId = tuple_class->relowner;
9514  }
9515  break;
9516  case RELKIND_SEQUENCE:
9517  if (!recursing &&
9518  tuple_class->relowner != newOwnerId)
9519  {
9520  /* if it's an owned sequence, disallow changing it by itself */
9521  Oid tableId;
9522  int32 colId;
9523 
9524  if (sequenceIsOwned(relationOid, &tableId, &colId))
9525  ereport(ERROR,
9526  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
9527  errmsg("cannot change owner of sequence \"%s\"",
9528  NameStr(tuple_class->relname)),
9529  errdetail("Sequence \"%s\" is linked to table \"%s\".",
9530  NameStr(tuple_class->relname),
9531  get_rel_name(tableId))));
9532  }
9533  break;
9535  if (recursing)
9536  break;
9537  ereport(ERROR,
9538  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
9539  errmsg("\"%s\" is a composite type",
9540  NameStr(tuple_class->relname)),
9541  errhint("Use ALTER TYPE instead.")));
9542  break;
9543  case RELKIND_TOASTVALUE:
9544  if (recursing)
9545  break;
9546  /* FALL THRU */
9547  default:
9548  ereport(ERROR,
9549  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
9550  errmsg("\"%s\" is not a table, view, sequence, or foreign table",
9551  NameStr(tuple_class->relname))));
9552  }
9553 
9554  /*
9555  * If the new owner is the same as the existing owner, consider the
9556  * command to have succeeded. This is for dump restoration purposes.
9557  */
9558  if (tuple_class->relowner != newOwnerId)
9559  {
9560  Datum repl_val[Natts_pg_class];
9561  bool repl_null[Natts_pg_class];
9562  bool repl_repl[Natts_pg_class];
9563  Acl *newAcl;
9564  Datum aclDatum;
9565  bool isNull;
9566  HeapTuple newtuple;
9567 
9568  /* skip permission checks when recursing to index or toast table */
9569  if (!recursing)
9570  {
9571  /* Superusers can always do it */
9572  if (!superuser())
9573  {
9574  Oid namespaceOid = tuple_class->relnamespace;
9575  AclResult aclresult;
9576 
9577  /* Otherwise, must be owner of the existing object */
9578  if (!pg_class_ownercheck(relationOid, GetUserId()))
9580  RelationGetRelationName(target_rel));
9581 
9582  /* Must be able to become new owner */
9583  check_is_member_of_role(GetUserId(), newOwnerId);
9584 
9585  /* New owner must have CREATE privilege on namespace */
9586  aclresult = pg_namespace_aclcheck(namespaceOid, newOwnerId,
9587  ACL_CREATE);
9588  if (aclresult != ACLCHECK_OK)
9590  get_namespace_name(namespaceOid));
9591  }
9592  }
9593 
9594  memset(repl_null, false, sizeof(repl_null));
9595  memset(repl_repl, false, sizeof(repl_repl));
9596 
9597  repl_repl[Anum_pg_class_relowner - 1] = true;
9598  repl_val[Anum_pg_class_relowner - 1] = ObjectIdGetDatum(newOwnerId);
9599 
9600  /*
9601  * Determine the modified ACL for the new owner. This is only
9602  * necessary when the ACL is non-null.
9603  */
9604  aclDatum = SysCacheGetAttr(RELOID, tuple,
9606  &isNull);
9607  if (!isNull)
9608  {
9609  newAcl = aclnewowner(DatumGetAclP(aclDatum),
9610  tuple_class->relowner, newOwnerId);
9611  repl_repl[Anum_pg_class_relacl - 1] = true;
9612  repl_val[Anum_pg_class_relacl - 1] = PointerGetDatum(newAcl);
9613  }
9614 
9615  newtuple = heap_modify_tuple(tuple, RelationGetDescr(class_rel), repl_val, repl_null, repl_repl);
9616 
9617  CatalogTupleUpdate(class_rel, &newtuple->t_self, newtuple);
9618 
9619  heap_freetuple(newtuple);
9620 
9621  /*
9622  * We must similarly update any per-column ACLs to reflect the new
9623  * owner; for neatness reasons that's split out as a subroutine.
9624  */
9625  change_owner_fix_column_acls(relationOid,
9626  tuple_class->relowner,
9627  newOwnerId);
9628 
9629  /*
9630  * Update owner dependency reference, if any. A composite type has
9631  * none, because it's tracked for the pg_type entry instead of here;
9632  * indexes and TOAST tables don't have their own entries either.
9633  */
9634  if (tuple_class->relkind != RELKIND_COMPOSITE_TYPE &&
9635  tuple_class->relkind != RELKIND_INDEX &&
9636  tuple_class->relkind != RELKIND_TOASTVALUE)
9638  newOwnerId);
9639 
9640  /*
9641  * Also change the ownership of the table's row type, if it has one
9642  */
9643  if (tuple_class->relkind != RELKIND_INDEX)
9644  AlterTypeOwnerInternal(tuple_class->reltype, newOwnerId);
9645 
9646  /*
9647  * If we are operating on a table or materialized view, also change
9648  * the ownership of any indexes and sequences that belong to the
9649  * relation, as well as its toast table (if it has one).
9650  */
9651  if (tuple_class->relkind == RELKIND_RELATION ||
9652  tuple_class->relkind == RELKIND_MATVIEW ||
9653  tuple_class->relkind == RELKIND_TOASTVALUE)
9654  {
9655  List *index_oid_list;
9656  ListCell *i;
9657 
9658  /* Find all the indexes belonging to this relation */
9659  index_oid_list = RelationGetIndexList(target_rel);
9660 
9661  /* For each index, recursively change its ownership */
9662  foreach(i, index_oid_list)
9663  ATExecChangeOwner(lfirst_oid(i), newOwnerId, true, lockmode);
9664 
9665  list_free(index_oid_list);
9666  }
9667 
9668  if (tuple_class->relkind == RELKIND_RELATION ||
9669  tuple_class->relkind == RELKIND_MATVIEW)
9670  {
9671  /* If it has a toast table, recurse to change its ownership */
9672  if (tuple_class->reltoastrelid != InvalidOid)
9673  ATExecChangeOwner(tuple_class->reltoastrelid, newOwnerId,
9674  true, lockmode);
9675 
9676  /* If it has dependent sequences, recurse to change them too */
9677  change_owner_recurse_to_sequences(relationOid, newOwnerId, lockmode);
9678  }
9679  }
9680 
9682 
9683  ReleaseSysCache(tuple);
9684  heap_close(class_rel, RowExclusiveLock);
9685  relation_close(target_rel, NoLock);
9686 }
#define Natts_pg_class
Definition: pg_class.h:102
bool sequenceIsOwned(Oid seqId, Oid *tableId, int32 *colId)
Definition: pg_depend.c:500
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
#define RelationGetDescr(relation)
Definition: rel.h:425
Oid GetUserId(void)
Definition: miscinit.c:282
#define DatumGetAclP(X)
Definition: acl.h:113
#define PointerGetDatum(X)
Definition: postgres.h:564
#define RelationRelationId
Definition: pg_class.h:29
#define RELKIND_MATVIEW
Definition: pg_class.h:167
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:1263
void AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId)
Definition: typecmds.c:3361
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1374
unsigned int Oid
Definition: postgres_ext.h:31
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4459
#define RELKIND_COMPOSITE_TYPE
Definition: pg_class.h:165
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:149
signed int int32
Definition: c.h:253
void changeDependencyOnOwner(Oid classId, Oid objectId, Oid newOwnerId)
Definition: pg_shdepend.c:303
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
#define ACL_CREATE
Definition: parsenodes.h:75
ItemPointerData t_self
Definition: htup.h:65
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3006
#define NoLock
Definition: lockdefs.h:34
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3378
#define RowExclusiveLock
Definition: lockdefs.h:38
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define RelationGetRelationName(relation)
Definition: rel.h:433
#define RELKIND_FOREIGN_TABLE
Definition: pg_class.h:166
void check_is_member_of_role(Oid member, Oid role)
Definition: acl.c:4877
#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:9465
#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:374
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1245
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
bool pg_class_ownercheck(Oid class_oid, Oid roleid)
Definition: aclchk.c:4521
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:9760
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4336
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:9695
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:495
#define RELKIND_INDEX
Definition: pg_class.h:161
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1117
#define elog
Definition: elog.h:219
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:793
#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:1694
Acl * aclnewowner(const Acl *old_acl, Oid oldOwnerId, Oid newOwnerId)
Definition: acl.c:1036
#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 4941 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().

4942 {
4943  Form_pg_type typ = (Form_pg_type) GETSTRUCT(typetuple);
4944  bool typeOk = false;
4945 
4946  if (typ->typtype == TYPTYPE_COMPOSITE)
4947  {
4948  Relation typeRelation;
4949 
4950  Assert(OidIsValid(typ->typrelid));
4951  typeRelation = relation_open(typ->typrelid, AccessShareLock);
4952  typeOk = (typeRelation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE);
4953 
4954  /*
4955  * Close the parent rel, but keep our AccessShareLock on it until xact
4956  * commit. That will prevent someone else from deleting or ALTERing
4957  * the type before the typed table creation/conversion commits.
4958  */
4959  relation_close(typeRelation, NoLock);
4960  }
4961  if (!typeOk)
4962  ereport(ERROR,
4963  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
4964  errmsg("type %s is not a composite type",
4965  format_type_be(HeapTupleGetOid(typetuple)))));
4966 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define TYPTYPE_COMPOSITE
Definition: pg_type.h:709
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:575
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1263
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:113
#define OidIsValid(objectId)
Definition: c.h:534
#define RELKIND_COMPOSITE_TYPE
Definition: pg_class.h:165
#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:671
int errmsg(const char *fmt,...)
Definition: elog.c:797
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1117
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
void CheckTableNotInUse ( Relation  rel,
const char *  stmt 
)

Definition at line 2950 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(), DefineVirtualRelation(), ExecRefreshMatView(), heap_drop_with_catalog(), index_drop(), reindex_index(), and truncate_check_rel().

2951 {
2952  int expected_refcnt;
2953 
2954  expected_refcnt = rel->rd_isnailed ? 2 : 1;
2955  if (rel->rd_refcnt != expected_refcnt)
2956  ereport(ERROR,
2957  (errcode(ERRCODE_OBJECT_IN_USE),
2958  /* translator: first %s is a SQL command, eg ALTER TABLE */
2959  errmsg("cannot %s \"%s\" because "
2960  "it is being used by active queries in this session",
2961  stmt, RelationGetRelationName(rel))));
2962 
2963  if (rel->rd_rel->relkind != RELKIND_INDEX &&
2965  ereport(ERROR,
2966  (errcode(ERRCODE_OBJECT_IN_USE),
2967  /* translator: first %s is a SQL command, eg ALTER TABLE */
2968  errmsg("cannot %s \"%s\" because "
2969  "it has pending trigger events",
2970  stmt, RelationGetRelationName(rel))));
2971 }
bool rd_isnailed
Definition: rel.h:91
int errcode(int sqlerrcode)
Definition: elog.c:575
Form_pg_class rd_rel
Definition: rel.h:113
#define ERROR
Definition: elog.h:43
#define RelationGetRelationName(relation)
Definition: rel.h:433
#define ereport(elevel, rest)
Definition: elog.h:122
bool AfterTriggerPendingOnRel(Oid relid)
Definition: trigger.c:5008
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:413
ObjectAddress DefineRelation ( CreateStmt stmt,
char  relkind,
Oid  ownerId,
ObjectAddress typaddress,
const char *  queryString 
)

Definition at line 481 of file tablecmds.c.

References AccessExclusiveLock, ACL_CREATE, ACL_KIND_TABLESPACE, ACL_USAGE, aclcheck_error(), aclcheck_error_type(), ACLCHECK_OK, AddRelationNewConstraints(), allowSystemTableMods, AlterTableInternal(), Assert, AT_SetNotNull, 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(), i, CookedConstraint::inhcount, CreateStmt::inhRelations, InSecurityRestrictedOperation(), interpretOidsOption(), InvalidOid, CookedConstraint::is_local, CookedConstraint::is_no_inherit, lappend(), lfirst, linitial_oid, list_concat(), list_length(), make_parsestate(), makeNode, MergeAttributes(), MyDatabaseTableSpace, CookedConstraint::name, AlterTableCmd::name, NAMEDATALEN, NameStr, NIL, NoLock, NULL, ObjectAddressSet, CreateStmt::ofTypename, OidIsValid, CreateStmt::oncommit, ONCOMMIT_NOOP, CreateStmt::options, ParseState::p_sourcetext, palloc(), CreateStmt::partbound, PARTITION_MAX_KEYS, PARTITION_STRATEGY_RANGE, PartitionSpec::partParams, CreateStmt::partspec, pg_tablespace_aclcheck(), pg_type_aclcheck(), pstrdup(), RangeVarGetAndCheckCreationNamespace(), RawColumnDefault::raw_default, ColumnDef::raw_default, RelationData::rd_rel, CreateStmt::relation, relation_close(), relation_open(), RelationGetRelationName, RelationGetRelid, RelationRelationId, RELKIND_PARTITIONED_TABLE, RELKIND_RELATION, RELKIND_VIEW, RangeVar::relname, RangeVar::relpersistence, RELPERSISTENCE_TEMP, CookedConstraint::skip_validation, StoreCatalogInheritance(), StorePartitionBound(), StorePartitionKey(), StrNCpy, AlterTableCmd::subtype, CreateStmt::tableElts, CreateStmt::tablespacename, tupleDesc::tdhasoid, transformPartitionBound(), transformPartitionSpec(), transformRelOptions(), typenameTypeId(), and view_reloptions().

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

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

1166 {
1167  List *rels = NIL;
1168  List *relids = NIL;
1169  List *seq_relids = NIL;
1170  EState *estate;
1171  ResultRelInfo *resultRelInfos;
1172  ResultRelInfo *resultRelInfo;
1173  SubTransactionId mySubid;
1174  ListCell *cell;
1175 
1176  /*
1177  * Open, exclusive-lock, and check all the explicitly-specified relations
1178  */
1179  foreach(cell, stmt->relations)
1180  {
1181  RangeVar *rv = lfirst(cell);
1182  Relation rel;
1183  bool recurse = rv->inh;
1184  Oid myrelid;
1185 
1186  rel = heap_openrv(rv, AccessExclusiveLock);
1187  myrelid = RelationGetRelid(rel);
1188  /* don't throw error for "TRUNCATE foo, foo" */
1189  if (list_member_oid(relids, myrelid))
1190  {
1192  continue;
1193  }
1194  truncate_check_rel(rel);
1195  rels = lappend(rels, rel);
1196  relids = lappend_oid(relids, myrelid);
1197 
1198  if (recurse)
1199  {
1200  ListCell *child;
1201  List *children;
1202 
1203  children = find_all_inheritors(myrelid, AccessExclusiveLock, NULL);
1204 
1205  foreach(child, children)
1206  {
1207  Oid childrelid = lfirst_oid(child);
1208 
1209  if (list_member_oid(relids, childrelid))
1210  continue;
1211 
1212  /* find_all_inheritors already got lock */
1213  rel = heap_open(childrelid, NoLock);
1214  truncate_check_rel(rel);
1215  rels = lappend(rels, rel);
1216  relids = lappend_oid(relids, childrelid);
1217  }
1218  }
1219  else if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1220  ereport(ERROR,
1221  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1222  errmsg("must truncate child tables too")));
1223  }
1224 
1225  /*
1226  * In CASCADE mode, suck in all referencing relations as well. This
1227  * requires multiple iterations to find indirectly-dependent relations. At
1228  * each phase, we need to exclusive-lock new rels before looking for their
1229  * dependencies, else we might miss something. Also, we check each rel as
1230  * soon as we open it, to avoid a faux pas such as holding lock for a long
1231  * time on a rel we have no permissions for.
1232  */
1233  if (stmt->behavior == DROP_CASCADE)
1234  {
1235  for (;;)
1236  {
1237  List *newrelids;
1238 
1239  newrelids = heap_truncate_find_FKs(relids);
1240  if (newrelids == NIL)
1241  break; /* nothing else to add */
1242 
1243  foreach(cell, newrelids)
1244  {
1245  Oid relid = lfirst_oid(cell);
1246  Relation rel;
1247 
1248  rel = heap_open(relid, AccessExclusiveLock);
1249  ereport(NOTICE,
1250  (errmsg("truncate cascades to table \"%s\"",
1251  RelationGetRelationName(rel))));
1252  truncate_check_rel(rel);
1253  rels = lappend(rels, rel);
1254  relids = lappend_oid(relids, relid);
1255  }
1256  }
1257  }
1258 
1259  /*
1260  * Check foreign key references. In CASCADE mode, this should be
1261  * unnecessary since we just pulled in all the references; but as a
1262  * cross-check, do it anyway if in an Assert-enabled build.
1263  */
1264 #ifdef USE_ASSERT_CHECKING
1265  heap_truncate_check_FKs(rels, false);
1266 #else
1267  if (stmt->behavior == DROP_RESTRICT)
1268  heap_truncate_check_FKs(rels, false);
1269 #endif
1270 
1271  /*
1272  * If we are asked to restart sequences, find all the sequences, lock them
1273  * (we need AccessExclusiveLock for ResetSequence), and check permissions.
1274  * We want to do this early since it's pointless to do all the truncation
1275  * work only to fail on sequence permissions.
1276  */
1277  if (stmt->restart_seqs)
1278  {
1279  foreach(cell, rels)
1280  {
1281  Relation rel = (Relation) lfirst(cell);
1282  List *seqlist = getOwnedSequences(RelationGetRelid(rel));
1283  ListCell *seqcell;
1284 
1285  foreach(seqcell, seqlist)
1286  {
1287  Oid seq_relid = lfirst_oid(seqcell);
1288  Relation seq_rel;
1289 
1290  seq_rel = relation_open(seq_relid, AccessExclusiveLock);
1291 
1292  /* This check must match AlterSequence! */
1293  if (!pg_class_ownercheck(seq_relid, GetUserId()))
1295  RelationGetRelationName(seq_rel));
1296 
1297  seq_relids = lappend_oid(seq_relids, seq_relid);
1298 
1299  relation_close(seq_rel, NoLock);
1300  }
1301  }
1302  }
1303 
1304  /* Prepare to catch AFTER triggers. */
1306 
1307  /*
1308  * To fire triggers, we'll need an EState as well as a ResultRelInfo for
1309  * each relation. We don't need to call ExecOpenIndices, though.
1310  */
1311  estate = CreateExecutorState();
1312  resultRelInfos = (ResultRelInfo *)
1313  palloc(list_length(rels) * sizeof(ResultRelInfo));
1314  resultRelInfo = resultRelInfos;
1315  foreach(cell, rels)
1316  {
1317  Relation rel = (Relation) lfirst(cell);
1318 
1319  InitResultRelInfo(resultRelInfo,
1320  rel,
1321  0, /* dummy rangetable index */
1322  NULL,
1323  0);
1324  resultRelInfo++;
1325  }
1326  estate->es_result_relations = resultRelInfos;
1327  estate->es_num_result_relations = list_length(rels);
1328 
1329  /*
1330  * Process all BEFORE STATEMENT TRUNCATE triggers before we begin
1331  * truncating (this is because one of them might throw an error). Also, if
1332  * we were to allow them to prevent statement execution, that would need
1333  * to be handled here.
1334  */
1335  resultRelInfo = resultRelInfos;
1336  foreach(cell, rels)
1337  {
1338  estate->es_result_relation_info = resultRelInfo;
1339  ExecBSTruncateTriggers(estate, resultRelInfo);
1340  resultRelInfo++;
1341  }
1342 
1343  /*
1344  * OK, truncate each table.
1345  */
1346  mySubid = GetCurrentSubTransactionId();
1347 
1348  foreach(cell, rels)
1349  {
1350  Relation rel = (Relation) lfirst(cell);
1351 
1352  /*
1353  * Normally, we need a transaction-safe truncation here. However, if
1354  * the table was either created in the current (sub)transaction or has
1355  * a new relfilenode in the current (sub)transaction, then we can just
1356  * truncate it in-place, because a rollback would cause the whole
1357  * table or the current physical file to be thrown away anyway.
1358  */
1359  if (rel->rd_createSubid == mySubid ||
1360  rel->rd_newRelfilenodeSubid == mySubid)
1361  {
1362  /* Immediate, non-rollbackable truncation is OK */
1363  heap_truncate_one_rel(rel);
1364  }
1365  else
1366  {
1367  Oid heap_relid;
1368  Oid toast_relid;
1369  MultiXactId minmulti;
1370 
1371  /*
1372  * This effectively deletes all rows in the table, and may be done
1373  * in a serializable transaction. In that case we must record a
1374  * rw-conflict in to this transaction from each transaction
1375  * holding a predicate lock on the table.
1376  */
1378 
1379  minmulti = GetOldestMultiXactId();
1380 
1381  /*
1382  * Need the full transaction-safe pushups.
1383  *
1384  * Create a new empty storage file for the relation, and assign it
1385  * as the relfilenode value. The old storage file is scheduled for
1386  * deletion at commit.
1387  */
1388  RelationSetNewRelfilenode(rel, rel->rd_rel->relpersistence,
1389  RecentXmin, minmulti);
1390  if (rel->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED)
1391  heap_create_init_fork(rel);
1392 
1393  heap_relid = RelationGetRelid(rel);
1394  toast_relid = rel->rd_rel->reltoastrelid;
1395 
1396  /*
1397  * The same for the toast table, if any.
1398  */
1399  if (OidIsValid(toast_relid))
1400  {
1401  rel = relation_open(toast_relid, AccessExclusiveLock);
1402  RelationSetNewRelfilenode(rel, rel->rd_rel->relpersistence,
1403  RecentXmin, minmulti);
1404  if (rel->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED)
1405  heap_create_init_fork(rel);
1406  heap_close(rel, NoLock);
1407  }
1408 
1409  /*
1410  * Reconstruct the indexes to match, and we're done.
1411  */
1413  }
1414 
1415  pgstat_count_truncate(rel);
1416  }
1417 
1418  /*
1419  * Restart owned sequences if we were asked to.
1420  */
1421  foreach(cell, seq_relids)
1422  {
1423  Oid seq_relid = lfirst_oid(cell);
1424 
1425  ResetSequence(seq_relid);
1426  }
1427 
1428  /*
1429  * Process all AFTER STATEMENT TRUNCATE triggers.
1430  */
1431  resultRelInfo = resultRelInfos;
1432  foreach(cell, rels)
1433  {
1434  estate->es_result_relation_info = resultRelInfo;
1435  ExecASTruncateTriggers(estate, resultRelInfo);
1436  resultRelInfo++;
1437  }
1438 
1439  /* Handle queued AFTER triggers */
1440  AfterTriggerEndQuery(estate);
1441 
1442  /* We can clean up the EState now */
1443  FreeExecutorState(estate);
1444 
1445  /* And close the rels (can't do this while EState still holds refs) */
1446  foreach(cell, rels)
1447  {
1448  Relation rel = (Relation) lfirst(cell);
1449 
1450  heap_close(rel, NoLock);
1451  }
1452 }
#define NIL
Definition: pg_list.h:69
void InitResultRelInfo(ResultRelInfo *resultRelInfo, Relation resultRelationDesc, Index resultRelationIndex, Relation partition_root, int instrument_options)
Definition: execMain.c:1221
void RelationSetNewRelfilenode(Relation relation, char persistence, TransactionId freezeXid, MultiXactId minmulti)
Definition: relcache.c:3414
#define RELPERSISTENCE_UNLOGGED
Definition: pg_class.h:171
Oid GetUserId(void)
Definition: miscinit.c:282
void heap_truncate_one_rel(Relation rel)
Definition: heap.c:2858
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:2895
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1263
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:110
uint32 SubTransactionId
Definition: c.h:398
#define heap_close(r, l)
Definition: heapam.h:97
Form_pg_class rd_rel
Definition: rel.h:113
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:534
void FreeExecutorState(EState *estate)
Definition: execUtils.c:168
DropBehavior behavior
Definition: parsenodes.h:2481
struct RelationData * Relation
Definition: relcache.h:21
void ExecBSTruncateTriggers(EState *estate, ResultRelInfo *relinfo)
Definition: trigger.c:2807
#define ERROR
Definition: elog.h:43
struct ResultRelInfo ResultRelInfo
List * relations
Definition: parsenodes.h:2479
#define NoLock
Definition: lockdefs.h:34
void heap_create_init_fork(Relation rel)
Definition: heap.c:1377
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3378
ResultRelInfo * es_result_relations
Definition: execnodes.h:382
bool restart_seqs
Definition: parsenodes.h:2480
void ExecASTruncateTriggers(EState *estate, ResultRelInfo *relinfo)
Definition: trigger.c:2859
#define RelationGetRelationName(relation)
Definition: rel.h:433
void pgstat_count_truncate(Relation rel)
Definition: pgstat.c:1906
#define ereport(elevel, rest)
Definition: elog.h:122
EState * CreateExecutorState(void)
Definition: execUtils.c:72
bool inh
Definition: primnodes.h:68
List * lappend(List *list, void *datum)
Definition: list.c:128
SubTransactionId rd_createSubid
Definition: rel.h:109
List * getOwnedSequences(Oid relid)
Definition: pg_depend.c:560
#define RELKIND_PARTITIONED_TABLE
Definition: pg_class.h:168
MultiXactId GetOldestMultiXactId(void)
Definition: multixact.c:2487
static void truncate_check_rel(Relation rel)
Definition: tablecmds.c:1458
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
int es_num_result_relations
Definition: execnodes.h:383
Relation heap_openrv(const RangeVar *relation, LOCKMODE lockmode)
Definition: heapam.c:1315
#define NOTICE
Definition: elog.h:37
void AfterTriggerBeginQuery(void)
Definition: trigger.c:4150
TransactionId MultiXactId
Definition: c.h:404
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:505
#define NULL
Definition: c.h:226
#define lfirst(lc)
Definition: pg_list.h:106
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:648
bool pg_class_ownercheck(Oid class_oid, Oid roleid)
Definition: aclchk.c:4521
static int list_length(const List *l)
Definition: pg_list.h:89
void CheckTableForSerializableConflictIn(Relation relation)
Definition: predicate.c:4327
#define AccessExclusiveLock
Definition: lockdefs.h:46
List * find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents)
Definition: pg_inherits.c:159
void AfterTriggerEndQuery(EState *estate)
Definition: trigger.c:4170
void * palloc(Size size)
Definition: mcxt.c:891
int errmsg(const char *fmt,...)
Definition: elog.c:797
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1117
#define REINDEX_REL_PROCESS_TOAST
Definition: index.h:122
void ResetSequence(Oid seq_relid)
Definition: sequence.c:263
bool reindex_relation(Oid relid, int flags, int options)
Definition: index.c:3515
Definition: pg_list.h:45
#define RelationGetRelid(relation)
Definition: rel.h:413
List * heap_truncate_find_FKs(List *relationIds)
Definition: heap.c:2987
#define lfirst_oid(lc)
Definition: pg_list.h:108
ResultRelInfo * es_result_relation_info
Definition: execnodes.h:384
void find_composite_type_dependencies ( Oid  typeOid,
Relation  origRelation,
const char *  origTypeName 
)

Definition at line 4786 of file tablecmds.c.

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

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

4788 {
4789  Relation depRel;
4790  ScanKeyData key[2];
4791  SysScanDesc depScan;
4792  HeapTuple depTup;
4793  Oid arrayOid;
4794 
4795  /*
4796  * We scan pg_depend to find those things that depend on the rowtype. (We
4797  * assume we can ignore refobjsubid for a rowtype.)
4798  */
4800 
4801  ScanKeyInit(&key[0],
4803  BTEqualStrategyNumber, F_OIDEQ,
4805  ScanKeyInit(&key[1],
4807  BTEqualStrategyNumber, F_OIDEQ,
4808  ObjectIdGetDatum(typeOid));
4809 
4810  depScan = systable_beginscan(depRel, DependReferenceIndexId, true,
4811  NULL, 2, key);
4812 
4813  while (HeapTupleIsValid(depTup = systable_getnext(depScan)))
4814  {
4815  Form_pg_depend pg_depend = (Form_pg_depend) GETSTRUCT(depTup);
4816  Relation rel;
4817  Form_pg_attribute att;
4818 
4819  /* Ignore dependees that aren't user columns of relations */
4820  /* (we assume system columns are never of rowtypes) */
4821  if (pg_depend->classid != RelationRelationId ||
4822  pg_depend->objsubid <= 0)
4823  continue;
4824 
4825  rel = relation_open(pg_depend->objid, AccessShareLock);
4826  att = rel->rd_att->attrs[pg_depend->objsubid - 1];
4827 
4828  if (rel->rd_rel->relkind == RELKIND_RELATION ||
4829  rel->rd_rel->relkind == RELKIND_MATVIEW ||
4830  rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
4831  {
4832  if (origTypeName)
4833  ereport(ERROR,
4834  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4835  errmsg("cannot alter type \"%s\" because column \"%s.%s\" uses it",
4836  origTypeName,
4838  NameStr(att->attname))));
4839  else if (origRelation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
4840  ereport(ERROR,
4841  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4842  errmsg("cannot alter type \"%s\" because column \"%s.%s\" uses it",
4843  RelationGetRelationName(origRelation),
4845  NameStr(att->attname))));
4846  else if (origRelation->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
4847  ereport(ERROR,
4848  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4849  errmsg("cannot alter foreign table \"%s\" because column \"%s.%s\" uses its row type",
4850  RelationGetRelationName(origRelation),
4852  NameStr(att->attname))));
4853  else
4854  ereport(ERROR,
4855  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4856  errmsg("cannot alter table \"%s\" because column \"%s.%s\" uses its row type",
4857  RelationGetRelationName(origRelation),
4859  NameStr(att->attname))));
4860  }
4861  else if (OidIsValid(rel->rd_rel->reltype))
4862  {
4863  /*
4864  * A view or composite type itself isn't a problem, but we must
4865  * recursively check for indirect dependencies via its rowtype.
4866  */
4868  origRelation, origTypeName);
4869  }
4870 
4872  }
4873 
4874  systable_endscan(depScan);
4875 
4877 
4878  /*
4879  * If there's an array type for the rowtype, must check for uses of it,
4880  * too.
4881  */
4882  arrayOid = get_array_type(typeOid);
4883  if (OidIsValid(arrayOid))
4884  find_composite_type_dependencies(arrayOid, origRelation, origTypeName);
4885 }
#define Anum_pg_depend_refobjid
Definition: pg_depend.h:72
#define Anum_pg_depend_refclassid
Definition: pg_depend.h:71
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:493
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
Oid get_array_type(Oid typid)
Definition: lsyscache.c:2480
#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:4786
#define DependRelationId
Definition: pg_depend.h:29
Form_pg_attribute * attrs
Definition: tupdesc.h:74
#define RELKIND_MATVIEW
Definition: pg_class.h:167
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:575
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1263
Form_pg_class rd_rel
Definition: rel.h:113
unsigned int Oid
Definition: postgres_ext.h:31
#define TypeRelationId
Definition: pg_type.h:34
#define OidIsValid(objectId)
Definition: c.h:534
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:322
#define RELKIND_COMPOSITE_TYPE
Definition: pg_class.h:165
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:410
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
#define RelationGetRelationName(relation)
Definition: rel.h:433
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:184
#define RELKIND_FOREIGN_TABLE
Definition: pg_class.h:166
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:1287
TupleDesc rd_att
Definition: rel.h:114
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define NameStr(name)
Definition: c.h:495
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:1117
#define RELKIND_RELATION
Definition: pg_class.h:160
#define BTEqualStrategyNumber
Definition: stratnum.h:31
void PreCommit_on_commit_actions ( void  )

Definition at line 12427 of file tablecmds.c.

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

Referenced by CommitTransaction(), and PrepareTransaction().

12428 {
12429  ListCell *l;
12430  List *oids_to_truncate = NIL;
12431 
12432  foreach(l, on_commits)
12433  {
12434  OnCommitItem *oc = (OnCommitItem *) lfirst(l);
12435 
12436  /* Ignore entry if already dropped in this xact */
12438  continue;
12439 
12440  switch (oc->oncommit)
12441  {
12442  case ONCOMMIT_NOOP:
12444  /* Do nothing (there shouldn't be such entries, actually) */
12445  break;
12446  case ONCOMMIT_DELETE_ROWS:
12447 
12448  /*
12449  * If this transaction hasn't accessed any temporary
12450  * relations, we can skip truncating ON COMMIT DELETE ROWS
12451  * tables, as they must still be empty.
12452  */
12454  oids_to_truncate = lappend_oid(oids_to_truncate, oc->relid);
12455  break;
12456  case ONCOMMIT_DROP:
12457  {
12458  ObjectAddress object;
12459 
12460  object.classId = RelationRelationId;
12461  object.objectId = oc->relid;
12462  object.objectSubId = 0;
12463 
12464  /*
12465  * Since this is an automatic drop, rather than one
12466  * directly initiated by the user, we pass the
12467  * PERFORM_DELETION_INTERNAL flag.
12468  */
12469  performDeletion(&object,
12471 
12472  /*
12473  * Note that table deletion will call
12474  * remove_on_commit_action, so the entry should get marked
12475  * as deleted.
12476  */
12478  break;
12479  }
12480  }
12481  }
12482  if (oids_to_truncate != NIL)
12483  {
12484  heap_truncate(oids_to_truncate);
12485  CommandCounterIncrement(); /* XXX needed? */
12486  }
12487 }
#define NIL
Definition: pg_list.h:69
OnCommitAction oncommit
Definition: tablecmds.c:111
#define RelationRelationId
Definition: pg_class.h:29
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
static List * on_commits
Definition: tablecmds.c:124
void performDeletion(const ObjectAddress *object, DropBehavior behavior, int flags)
Definition: dependency.c:301
bool MyXactAccessedTempRel
Definition: xact.c:116
SubTransactionId deleting_subid
Definition: tablecmds.c:121
void CommandCounterIncrement(void)
Definition: xact.c:921
#define Assert(condition)
Definition: c.h:671
#define lfirst(lc)
Definition: pg_list.h:106
void heap_truncate(List *relids)
Definition: heap.c:2817
#define InvalidSubTransactionId
Definition: c.h:400
Definition: pg_list.h:45
#define PERFORM_DELETION_INTERNAL
Definition: dependency.h:173
void RangeVarCallbackOwnsRelation ( const RangeVar relation,
Oid  relId,
Oid  oldRelId,
void *  noCatalogs 
)

Definition at line 12618 of file tablecmds.c.

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

Referenced by ProcessUtilitySlow().

12620 {
12621  HeapTuple tuple;
12622 
12623  /* Nothing to do if the relation was not found. */
12624  if (!OidIsValid(relId))
12625  return;
12626 
12627  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relId));
12628  if (!HeapTupleIsValid(tuple)) /* should not happen */
12629  elog(ERROR, "cache lookup failed for relation %u", relId);
12630 
12631  if (!pg_class_ownercheck(relId, GetUserId()))
12633  relation->relname);
12634 
12635  if (!allowSystemTableMods &&
12636  IsSystemClass(relId, (Form_pg_class) GETSTRUCT(tuple)))
12637  ereport(ERROR,
12638  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
12639  errmsg("permission denied: \"%s\" is a system catalog",
12640  relation->relname)));
12641 
12642  ReleaseSysCache(tuple);
12643 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
Oid GetUserId(void)
Definition: miscinit.c:282
int errcode(int sqlerrcode)
Definition: elog.c:575
#define OidIsValid(objectId)
Definition: c.h:534
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:149
bool IsSystemClass(Oid relid, Form_pg_class reltuple)
Definition: catalog.c:74
char * relname
Definition: primnodes.h:67
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3378
#define ereport(elevel, rest)
Definition: elog.h:122
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
bool allowSystemTableMods
Definition: globals.c:111
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
bool pg_class_ownercheck(Oid class_oid, Oid roleid)
Definition: aclchk.c:4521
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 12585 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().

12587 {
12588  char relkind;
12589 
12590  /* Nothing to do if the relation was not found. */
12591  if (!OidIsValid(relId))
12592  return;
12593 
12594  /*
12595  * If the relation does exist, check whether it's an index. But note that
12596  * the relation might have been dropped between the time we did the name
12597  * lookup and now. In that case, there's nothing to do.
12598  */
12599  relkind = get_rel_relkind(relId);
12600  if (!relkind)
12601  return;
12602  if (relkind != RELKIND_RELATION && relkind != RELKIND_TOASTVALUE &&
12603  relkind != RELKIND_MATVIEW && relkind != RELKIND_PARTITIONED_TABLE)
12604  ereport(ERROR,
12605  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
12606  errmsg("\"%s\" is not a table or materialized view", relation->relname)));
12607 
12608  /* Check permissions */
12609  if (!pg_class_ownercheck(relId, GetUserId()))
12611 }
Oid GetUserId(void)
Definition: miscinit.c:282
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:1769
#define RELKIND_MATVIEW
Definition: pg_class.h:167
int errcode(int sqlerrcode)
Definition: elog.c:575
#define OidIsValid(objectId)
Definition: c.h:534
char * relname
Definition: primnodes.h:67
#define ERROR
Definition: elog.h:43
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3378
#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:4521
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 12373 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().

12374 {
12375  OnCommitItem *oc;
12376  MemoryContext oldcxt;
12377 
12378  /*
12379  * We needn't bother registering the relation unless there is an ON COMMIT
12380  * action we need to take.
12381  */
12382  if (action == ONCOMMIT_NOOP || action == ONCOMMIT_PRESERVE_ROWS)
12383  return;
12384 
12386 
12387  oc = (OnCommitItem *) palloc(sizeof(OnCommitItem));
12388  oc->relid = relid;
12389  oc->oncommit = action;
12392 
12393  on_commits = lcons(oc, on_commits);
12394 
12395  MemoryContextSwitchTo(oldcxt);
12396 }
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:648
#define InvalidSubTransactionId
Definition: c.h:400
void * palloc(Size size)
Definition: mcxt.c:891
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
void remove_on_commit_action ( Oid  relid)

Definition at line 12404 of file tablecmds.c.

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

Referenced by heap_drop_with_catalog().

12405 {
12406  ListCell *l;
12407 
12408  foreach(l, on_commits)
12409  {
12410  OnCommitItem *oc = (OnCommitItem *) lfirst(l);
12411 
12412  if (oc->relid == relid)
12413  {
12415  break;
12416  }
12417  }
12418 }
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:648
void RemoveRelations ( DropStmt drop)

Definition at line 953 of file tablecmds.c.

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

Referenced by ExecDropStmt().

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

2623 {
2624  Oid relid;
2625  AttrNumber attnum;
2626  ObjectAddress address;
2627 
2628  /* lock level taken here should match renameatt_internal */
2630  stmt->missing_ok, false,
2632  NULL);
2633 
2634  if (!OidIsValid(relid))
2635  {
2636  ereport(NOTICE,
2637  (errmsg("relation \"%s\" does not exist, skipping",
2638  stmt->relation->relname)));
2639  return InvalidObjectAddress;
2640  }
2641 
2642  attnum =
2643  renameatt_internal(relid,
2644  stmt->subname, /* old att name */
2645  stmt->newname, /* new att name */
2646  stmt->relation->inh, /* recursive? */
2647  false, /* recursing? */
2648  0, /* expected inhcount */
2649  stmt->behavior);
2650 
2651  ObjectAddressSubSet(address, RelationRelationId, relid, attnum);
2652 
2653  return address;
2654 }
char * subname
Definition: parsenodes.h:2682
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, bool missing_ok, bool nowait, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:217
#define RelationRelationId
Definition: pg_class.h:29
char * newname
Definition: parsenodes.h:2684
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:534
char * relname
Definition: primnodes.h:67
bool missing_ok
Definition: parsenodes.h:2686
#define ereport(elevel, rest)
Definition: elog.h:122
bool inh
Definition: primnodes.h:68
RangeVar * relation
Definition: parsenodes.h:2679
#define NOTICE
Definition: elog.h:37
static void RangeVarCallbackForRenameAttribute(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg)
Definition: tablecmds.c:2602
#define NULL
Definition: c.h:226
static AttrNumber renameatt_internal(Oid myrelid, const char *oldattname, const char *newattname, bool recurse, bool recursing, int expected_parents, DropBehavior behavior)
Definition: tablecmds.c:2457
#define ObjectAddressSubSet(addr, class_id, object_id, object_sub_id)
Definition: objectaddress.h:33
#define AccessExclusiveLock
Definition: lockdefs.h:46
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:797
DropBehavior behavior
Definition: parsenodes.h:2685
int16 AttrNumber
Definition: attnum.h:21
ObjectAddress renameatt_type ( RenameStmt stmt)
ObjectAddress RenameConstraint ( RenameStmt stmt)

Definition at line 2759 of file tablecmds.c.

References AccessExclusiveLock, 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().

2760 {
2761  Oid relid = InvalidOid;
2762  Oid typid = InvalidOid;
2763 
2764  if (stmt->renameType == OBJECT_DOMCONSTRAINT)
2765  {
2766  Relation rel;
2767  HeapTuple tup;
2768 
2771  tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2772  if (!HeapTupleIsValid(tup))
2773  elog(ERROR, "cache lookup failed for type %u", typid);
2774  checkDomainOwner(tup);
2775  ReleaseSysCache(tup);
2776  heap_close(rel, NoLock);
2777  }
2778  else
2779  {
2780  /* lock level taken here should match rename_constraint_internal */
2782  stmt->missing_ok, false,
2784  NULL);
2785  if (!OidIsValid(relid))
2786  {
2787  ereport(NOTICE,
2788  (errmsg("relation \"%s\" does not exist, skipping",
2789  stmt->relation->relname)));
2790  return InvalidObjectAddress;
2791  }
2792  }
2793 
2794  return
2795  rename_constraint_internal(relid, typid,
2796  stmt->subname,
2797  stmt->newname,
2798  (stmt->relation &&
2799  stmt->relation->inh), /* recursive? */
2800  false, /* recursing? */
2801  0 /* expected inhcount */ );
2802 
2803 }
char * subname
Definition: parsenodes.h:2682
ObjectType renameType
Definition: parsenodes.h:2677
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, bool missing_ok, bool nowait, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:217
#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:2660
char * newname
Definition: parsenodes.h:2684
unsigned int Oid
Definition: postgres_ext.h:31
#define TypeRelationId
Definition: pg_type.h:34
#define OidIsValid(objectId)
Definition: c.h:534
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:149
char * relname
Definition: primnodes.h:67
bool missing_ok
Definition: parsenodes.h:2686
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ereport(elevel, rest)
Definition: elog.h:122
bool inh
Definition: primnodes.h:68
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
RangeVar * relation
Definition: parsenodes.h:2679
#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:2602
#define NULL
Definition: c.h:226
void checkDomainOwner(HeapTuple tup)
Definition: typecmds.c:2952
#define AccessExclusiveLock
Definition: lockdefs.h:46
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:797
TypeName * makeTypeNameFromNameList(List *names)
Definition: makefuncs.c:453
#define elog
Definition: elog.h:219
List * object
Definition: parsenodes.h:2680
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:274
ObjectAddress RenameRelation ( RenameStmt stmt)

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

2811 {
2812  Oid relid;
2813  ObjectAddress address;
2814 
2815  /*
2816  * Grab an exclusive lock on the target table, index, sequence, view,
2817  * materialized view, or foreign table, which we will NOT release until
2818  * end of transaction.
2819  *
2820  * Lock level used here should match RenameRelationInternal, to avoid lock
2821  * escalation.
2822  */
2824  stmt->missing_ok, false,
2826  (void *) stmt);
2827 
2828  if (!OidIsValid(relid))
2829  {
2830  ereport(NOTICE,
2831  (errmsg("relation \"%s\" does not exist, skipping",
2832  stmt->relation->relname)));
2833  return InvalidObjectAddress;
2834  }
2835 
2836  /* Do the work */
2837  RenameRelationInternal(relid, stmt->newname, false);
2838 
2839  ObjectAddressSet(address, RelationRelationId, relid);
2840 
2841  return address;
2842 }
void RenameRelationInternal(Oid myrelid, const char *newrelname, bool is_internal)
Definition: tablecmds.c:2854
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, bool missing_ok, bool nowait, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:217
#define RelationRelationId
Definition: pg_class.h:29
char * newname
Definition: parsenodes.h:2684
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:534
char * relname
Definition: primnodes.h:67
bool missing_ok
Definition: parsenodes.h:2686
static void RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg)
Definition: tablecmds.c:12650
#define ereport(elevel, rest)
Definition: elog.h:122
RangeVar * relation
Definition: parsenodes.h:2679
#define NOTICE
Definition: elog.h:37
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define AccessExclusiveLock
Definition: lockdefs.h:46
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:797
void RenameRelationInternal ( Oid  myrelid,
const char *  newrelname,
bool  is_internal 
)

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

2855 {
2856  Relation targetrelation;
2857  Relation relrelation; /* for RELATION relation */
2858  HeapTuple reltup;
2859  Form_pg_class relform;
2860  Oid namespaceId;
2861 
2862  /*
2863  * Grab an exclusive lock on the target table, index, sequence, view,
2864  * materialized view, or foreign table, which we will NOT release until
2865  * end of transaction.
2866  */
2867  targetrelation = relation_open(myrelid, AccessExclusiveLock);
2868  namespaceId = RelationGetNamespace(targetrelation);
2869 
2870  /*
2871  * Find relation's pg_class tuple, and make sure newrelname isn't in use.
2872  */
2874 
2875  reltup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(myrelid));
2876  if (!HeapTupleIsValid(reltup)) /* shouldn't happen */
2877  elog(ERROR, "cache lookup failed for relation %u", myrelid);
2878  relform = (Form_pg_class) GETSTRUCT(reltup);
2879 
2880  if (get_relname_relid(newrelname, namespaceId) != InvalidOid)
2881  ereport(ERROR,
2882  (errcode(ERRCODE_DUPLICATE_TABLE),
2883  errmsg("relation \"%s\" already exists",
2884  newrelname)));
2885 
2886  /*
2887  * Update pg_class tuple with new relname. (Scribbling on reltup is OK
2888  * because it's a copy...)
2889  */
2890  namestrcpy(&(relform->relname), newrelname);
2891 
2892  CatalogTupleUpdate(relrelation, &reltup->t_self, reltup);
2893 
2895  InvalidOid, is_internal);
2896 
2897  heap_freetuple(reltup);
2898  heap_close(relrelation, RowExclusiveLock);
2899 
2900  /*
2901  * Also rename the associated type, if any.
2902  */
2903  if (OidIsValid(targetrelation->rd_rel->reltype))
2904  RenameTypeInternal(targetrelation->rd_rel->reltype,
2905  newrelname, namespaceId);
2906 
2907  /*
2908  * Also rename the associated constraint, if any.
2909  */
2910  if (targetrelation->rd_rel->relkind == RELKIND_INDEX)
2911  {
2912  Oid constraintId = get_index_constraint(myrelid);
2913 
2914  if (OidIsValid(constraintId))
2915  RenameConstraintById(constraintId, newrelname);
2916  }
2917 
2918  /*
2919  * Close rel, but keep exclusive lock!
2920  */
2921  relation_close(targetrelation, NoLock);
2922 }
#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:1263
#define heap_close(r, l)
Definition: heapam.h:97
Form_pg_class rd_rel
Definition: rel.h:113
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1374
unsigned int Oid
Definition: postgres_ext.h:31
int namestrcpy(Name name, const char *str)
Definition: name.c:217
#define OidIsValid(objectId)
Definition: c.h:534
void RenameConstraintById(Oid conId, const char *newname)
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
Oid get_relname_relid(const char *relname, Oid relnamespace)
Definition: lsyscache.c:1651
#define NoLock
Definition: lockdefs.h:34
#define InvokeObjectPostAlterHookArg(classId, objectId, subId,auxiliaryId, is_internal)
Definition: objectaccess.h:166
#define RowExclusiveLock
Definition: lockdefs.h:38
Oid get_index_constraint(Oid indexId)
Definition: pg_depend.c:676
#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:1287
#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:158
#define AccessExclusiveLock
Definition: lockdefs.h:46
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:1117
#define elog
Definition: elog.h:219
#define RelationGetNamespace(relation)
Definition: rel.h:440
void SetRelationHasSubclass ( Oid  relationId,
bool  relhassubclass 
)

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

2377 {
2378  Relation relationRelation;
2379  HeapTuple tuple;
2380  Form_pg_class classtuple;
2381 
2382  /*
2383  * Fetch a modifiable copy of the tuple, modify it, update pg_class.
2384  */
2385  relationRelation = heap_open(RelationRelationId, RowExclusiveLock);
2386  tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relationId));
2387  if (!HeapTupleIsValid(tuple))
2388  elog(ERROR, "cache lookup failed for relation %u", relationId);
2389  classtuple = (Form_pg_class) GETSTRUCT(tuple);
2390 
2391  if (classtuple->relhassubclass != relhassubclass)
2392  {
2393  classtuple->relhassubclass = relhassubclass;
2394  CatalogTupleUpdate(relationRelation, &tuple->t_self, tuple);
2395  }
2396  else
2397  {
2398  /* no need to change tuple, but force relcache rebuild anyway */
2400  }
2401 
2402  heap_freetuple(tuple);
2403  heap_close(relationRelation, RowExclusiveLock);
2404 }
#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:1374
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
#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:158
void CacheInvalidateRelcacheByTuple(HeapTuple classTuple)
Definition: inval.c:1261
#define elog
Definition: elog.h:219