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 "catalog/partition.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)
 
bool PartConstraintImpliedByRelConstraint (Relation scanrel, List *partConstraint)
 

Function Documentation

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

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

12659 {
12660  HeapTuple classTup;
12661  Form_pg_class classForm;
12662  ObjectAddress thisobj;
12663  bool already_done = false;
12664 
12665  classTup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relOid));
12666  if (!HeapTupleIsValid(classTup))
12667  elog(ERROR, "cache lookup failed for relation %u", relOid);
12668  classForm = (Form_pg_class) GETSTRUCT(classTup);
12669 
12670  Assert(classForm->relnamespace == oldNspOid);
12671 
12672  thisobj.classId = RelationRelationId;
12673  thisobj.objectId = relOid;
12674  thisobj.objectSubId = 0;
12675 
12676  /*
12677  * If the object has already been moved, don't move it again. If it's
12678  * already in the right place, don't move it, but still fire the object
12679  * access hook.
12680  */
12681  already_done = object_address_present(&thisobj, objsMoved);
12682  if (!already_done && oldNspOid != newNspOid)
12683  {
12684  /* check for duplicate name (more friendly than unique-index failure) */
12685  if (get_relname_relid(NameStr(classForm->relname),
12686  newNspOid) != InvalidOid)
12687  ereport(ERROR,
12688  (errcode(ERRCODE_DUPLICATE_TABLE),
12689  errmsg("relation \"%s\" already exists in schema \"%s\"",
12690  NameStr(classForm->relname),
12691  get_namespace_name(newNspOid))));
12692 
12693  /* classTup is a copy, so OK to scribble on */
12694  classForm->relnamespace = newNspOid;
12695 
12696  CatalogTupleUpdate(classRel, &classTup->t_self, classTup);
12697 
12698  /* Update dependency on schema if caller said so */
12699  if (hasDependEntry &&
12701  relOid,
12703  oldNspOid,
12704  newNspOid) != 1)
12705  elog(ERROR, "failed to change schema dependency for relation \"%s\"",
12706  NameStr(classForm->relname));
12707  }
12708  if (!already_done)
12709  {
12710  add_exact_object_address(&thisobj, objsMoved);
12711 
12713  }
12714 
12715  heap_freetuple(classTup);
12716 }
#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:2170
int errcode(int sqlerrcode)
Definition: elog.c:575
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2110
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
Oid get_relname_relid(const char *relname, Oid relnamespace)
Definition: lsyscache.c:1683
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3033
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:681
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:173
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:493
#define elog
Definition: elog.h:219
void AlterTable ( Oid  relid,
LOCKMODE  lockmode,
AlterTableStmt stmt 
)

Definition at line 3141 of file tablecmds.c.

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

Referenced by ProcessUtilitySlow().

3142 {
3143  Relation rel;
3144 
3145  /* Caller is required to provide an adequate lock. */
3146  rel = relation_open(relid, NoLock);
3147 
3148  CheckTableNotInUse(rel, "ALTER TABLE");
3149 
3150  ATController(stmt, rel, stmt->cmds, stmt->relation->inh, lockmode);
3151 }
static void ATController(AlterTableStmt *parsetree, Relation rel, List *cmds, bool recurse, LOCKMODE lockmode)
Definition: tablecmds.c:3458
#define NoLock
Definition: lockdefs.h:34
void CheckTableNotInUse(Relation rel, const char *stmt)
Definition: tablecmds.c:3062
bool inh
Definition: primnodes.h:69
RangeVar * relation
Definition: parsenodes.h:1691
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1120
LOCKMODE AlterTableGetLockLevel ( List cmds)

Definition at line 3210 of file tablecmds.c.

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

Referenced by AlterTableInternal(), and ProcessUtilitySlow().

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

Definition at line 3165 of file tablecmds.c.

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

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

3166 {
3167  Relation rel;
3168  LOCKMODE lockmode = AlterTableGetLockLevel(cmds);
3169 
3170  rel = relation_open(relid, lockmode);
3171 
3173 
3174  ATController(NULL, rel, cmds, recurse, lockmode);
3175 }
int LOCKMODE
Definition: lockdefs.h:26
static void ATController(AlterTableStmt *parsetree, Relation rel, List *cmds, bool recurse, LOCKMODE lockmode)
Definition: tablecmds.c:3458
LOCKMODE AlterTableGetLockLevel(List *cmds)
Definition: tablecmds.c:3210
void EventTriggerAlterTableRelid(Oid objectId)
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1120
Oid AlterTableLookupRelation ( AlterTableStmt stmt,
LOCKMODE  lockmode 
)

Definition at line 3091 of file tablecmds.c.

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

Referenced by ProcessUtilitySlow().

3092 {
3093  return RangeVarGetRelidExtended(stmt->relation, lockmode, stmt->missing_ok, false,
3095  (void *) stmt);
3096 }
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, bool missing_ok, bool nowait, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:218
static void RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg)
Definition: tablecmds.c:13132
RangeVar * relation
Definition: parsenodes.h:1691
Oid AlterTableMoveAll ( AlterTableMoveAllStmt stmt)

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

10734 {
10735  List *relations = NIL;
10736  ListCell *l;
10737  ScanKeyData key[1];
10738  Relation rel;
10739  HeapScanDesc scan;
10740  HeapTuple tuple;
10741  Oid orig_tablespaceoid;
10742  Oid new_tablespaceoid;
10743  List *role_oids = roleSpecsToIds(stmt->roles);
10744 
10745  /* Ensure we were not asked to move something we can't */
10746  if (stmt->objtype != OBJECT_TABLE && stmt->objtype != OBJECT_INDEX &&
10747  stmt->objtype != OBJECT_MATVIEW)
10748  ereport(ERROR,
10749  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
10750  errmsg("only tables, indexes, and materialized views exist in tablespaces")));
10751 
10752  /* Get the orig and new tablespace OIDs */
10753  orig_tablespaceoid = get_tablespace_oid(stmt->orig_tablespacename, false);
10754  new_tablespaceoid = get_tablespace_oid(stmt->new_tablespacename, false);
10755 
10756  /* Can't move shared relations in to or out of pg_global */
10757  /* This is also checked by ATExecSetTableSpace, but nice to stop earlier */
10758  if (orig_tablespaceoid == GLOBALTABLESPACE_OID ||
10759  new_tablespaceoid == GLOBALTABLESPACE_OID)
10760  ereport(ERROR,
10761  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
10762  errmsg("cannot move relations in to or out of pg_global tablespace")));
10763 
10764  /*
10765  * Must have CREATE rights on the new tablespace, unless it is the
10766  * database default tablespace (which all users implicitly have CREATE
10767  * rights on).
10768  */
10769  if (OidIsValid(new_tablespaceoid) && new_tablespaceoid != MyDatabaseTableSpace)
10770  {
10771  AclResult aclresult;
10772 
10773  aclresult = pg_tablespace_aclcheck(new_tablespaceoid, GetUserId(),
10774  ACL_CREATE);
10775  if (aclresult != ACLCHECK_OK)
10777  get_tablespace_name(new_tablespaceoid));
10778  }
10779 
10780  /*
10781  * Now that the checks are done, check if we should set either to
10782  * InvalidOid because it is our database's default tablespace.
10783  */
10784  if (orig_tablespaceoid == MyDatabaseTableSpace)
10785  orig_tablespaceoid = InvalidOid;
10786 
10787  if (new_tablespaceoid == MyDatabaseTableSpace)
10788  new_tablespaceoid = InvalidOid;
10789 
10790  /* no-op */
10791  if (orig_tablespaceoid == new_tablespaceoid)
10792  return new_tablespaceoid;
10793 
10794  /*
10795  * Walk the list of objects in the tablespace and move them. This will
10796  * only find objects in our database, of course.
10797  */
10798  ScanKeyInit(&key[0],
10800  BTEqualStrategyNumber, F_OIDEQ,
10801  ObjectIdGetDatum(orig_tablespaceoid));
10802 
10804  scan = heap_beginscan_catalog(rel, 1, key);
10805  while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
10806  {
10807  Oid relOid = HeapTupleGetOid(tuple);
10808  Form_pg_class relForm;
10809 
10810  relForm = (Form_pg_class) GETSTRUCT(tuple);
10811 
10812  /*
10813  * Do not move objects in pg_catalog as part of this, if an admin
10814  * really wishes to do so, they can issue the individual ALTER
10815  * commands directly.
10816  *
10817  * Also, explicitly avoid any shared tables, temp tables, or TOAST
10818  * (TOAST will be moved with the main table).
10819  */
10820  if (IsSystemNamespace(relForm->relnamespace) || relForm->relisshared ||
10821  isAnyTempNamespace(relForm->relnamespace) ||
10822  relForm->relnamespace == PG_TOAST_NAMESPACE)
10823  continue;
10824 
10825  /* Only move the object type requested */
10826  if ((stmt->objtype == OBJECT_TABLE &&
10827  relForm->relkind != RELKIND_RELATION &&
10828  relForm->relkind != RELKIND_PARTITIONED_TABLE) ||
10829  (stmt->objtype == OBJECT_INDEX &&
10830  relForm->relkind != RELKIND_INDEX) ||
10831  (stmt->objtype == OBJECT_MATVIEW &&
10832  relForm->relkind != RELKIND_MATVIEW))
10833  continue;
10834 
10835  /* Check if we are only moving objects owned by certain roles */
10836  if (role_oids != NIL && !list_member_oid(role_oids, relForm->relowner))
10837  continue;
10838 
10839  /*
10840  * Handle permissions-checking here since we are locking the tables
10841  * and also to avoid doing a bunch of work only to fail part-way. Note
10842  * that permissions will also be checked by AlterTableInternal().
10843  *
10844  * Caller must be considered an owner on the table to move it.
10845  */
10846  if (!pg_class_ownercheck(relOid, GetUserId()))
10848  NameStr(relForm->relname));
10849 
10850  if (stmt->nowait &&
10852  ereport(ERROR,
10853  (errcode(ERRCODE_OBJECT_IN_USE),
10854  errmsg("aborting because lock on relation \"%s.%s\" is not available",
10855  get_namespace_name(relForm->relnamespace),
10856  NameStr(relForm->relname))));
10857  else
10859 
10860  /* Add to our list of objects to move */
10861  relations = lappend_oid(relations, relOid);
10862  }
10863 
10864  heap_endscan(scan);
10866 
10867  if (relations == NIL)
10868  ereport(NOTICE,
10869  (errcode(ERRCODE_NO_DATA_FOUND),
10870  errmsg("no matching relations in tablespace \"%s\" found",
10871  orig_tablespaceoid == InvalidOid ? "(database default)" :
10872  get_tablespace_name(orig_tablespaceoid))));
10873 
10874  /* Everything is locked, loop through and move all of the relations. */
10875  foreach(l, relations)
10876  {
10877  List *cmds = NIL;
10879 
10880  cmd->subtype = AT_SetTableSpace;
10881  cmd->name = stmt->new_tablespacename;
10882 
10883  cmds = lappend(cmds, cmd);
10884 
10886  /* OID is set by AlterTableInternal */
10887  AlterTableInternal(lfirst_oid(l), cmds, false);
10889  }
10890 
10891  return new_tablespaceoid;
10892 }
#define NIL
Definition: pg_list.h:69
bool ConditionalLockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:138
Oid get_tablespace_oid(const char *tablespacename, bool missing_ok)
Definition: tablespace.c:1380
AclResult pg_tablespace_aclcheck(Oid spc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4496
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
void heap_endscan(HeapScanDesc scan)
Definition: heapam.c:1565
Oid GetUserId(void)
Definition: miscinit.c:284
#define RelationRelationId
Definition: pg_class.h:29
#define Anum_pg_class_reltablespace
Definition: pg_class.h:110
#define RELKIND_MATVIEW
Definition: pg_class.h:165
#define AccessShareLock
Definition: lockdefs.h:36
#define GLOBALTABLESPACE_OID
Definition: pg_tablespace.h:64
Definition: nodes.h:510
int errcode(int sqlerrcode)
Definition: elog.c:575
AlterTableType subtype
Definition: parsenodes.h:1778
#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:532
Oid MyDatabaseTableSpace
Definition: globals.c:79
void EventTriggerAlterTableStart(Node *parsetree)
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define ACL_CREATE
Definition: parsenodes.h:82
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3033
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3399
HeapScanDesc heap_beginscan_catalog(Relation relation, int nkeys, ScanKey key)
Definition: heapam.c:1405
#define ereport(elevel, rest)
Definition: elog.h:122
List * lappend(List *list, void *datum)
Definition: list.c:128
#define RELKIND_PARTITIONED_TABLE
Definition: pg_class.h:168
AclResult
Definition: acl.h:178
HeapTuple heap_getnext(HeapScanDesc scan, ScanDirection direction)
Definition: heapam.c:1808
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
bool IsSystemNamespace(Oid namespaceId)
Definition: catalog.c:163
#define InvalidOid
Definition: postgres_ext.h:36
#define NOTICE
Definition: elog.h:37
#define makeNode(_type_)
Definition: nodes.h:558
List * roleSpecsToIds(List *memberNames)
Definition: user.c:1396
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:505
bool pg_class_ownercheck(Oid class_oid, Oid roleid)
Definition: aclchk.c:4546
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
void AlterTableInternal(Oid relid, List *cmds, bool recurse)
Definition: tablecmds.c:3165
#define AccessExclusiveLock
Definition: lockdefs.h:45
int errmsg(const char *fmt,...)
Definition: elog.c:797
char * get_tablespace_name(Oid spc_oid)
Definition: tablespace.c:1426
#define NameStr(name)
Definition: c.h:493
#define RELKIND_INDEX
Definition: pg_class.h:161
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
bool isAnyTempNamespace(Oid namespaceId)
Definition: namespace.c:3156
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:105
#define RELKIND_RELATION
Definition: pg_class.h:160
Definition: pg_list.h:45
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define lfirst_oid(lc)
Definition: pg_list.h:108
void EventTriggerAlterTableEnd(void)
ObjectAddress AlterTableNamespace ( AlterObjectSchemaStmt stmt,
Oid oldschema 
)

Definition at line 12546 of file tablecmds.c.

References AccessExclusiveLock, AlterTableNamespaceInternal(), CheckSetNamespace(), DEPENDENCY_AUTO, DEPENDENCY_INTERNAL, ereport, errcode(), errdetail(), errmsg(), ERROR, free_object_addresses(), get_rel_name(), InvalidObjectAddress, makeRangeVar(), AlterObjectSchemaStmt::missing_ok, new_object_addresses(), AlterObjectSchemaStmt::newschema, NoLock, NOTICE, 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().

12547 {
12548  Relation rel;
12549  Oid relid;
12550  Oid oldNspOid;
12551  Oid nspOid;
12552  RangeVar *newrv;
12553  ObjectAddresses *objsMoved;
12554  ObjectAddress myself;
12555 
12557  stmt->missing_ok, false,
12559  (void *) stmt);
12560 
12561  if (!OidIsValid(relid))
12562  {
12563  ereport(NOTICE,
12564  (errmsg("relation \"%s\" does not exist, skipping",
12565  stmt->relation->relname)));
12566  return InvalidObjectAddress;
12567  }
12568 
12569  rel = relation_open(relid, NoLock);
12570 
12571  oldNspOid = RelationGetNamespace(rel);
12572 
12573  /* If it's an owned sequence, disallow moving it by itself. */
12574  if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
12575  {
12576  Oid tableId;
12577  int32 colId;
12578 
12579  if (sequenceIsOwned(relid, DEPENDENCY_AUTO, &tableId, &colId) ||
12580  sequenceIsOwned(relid, DEPENDENCY_INTERNAL, &tableId, &colId))
12581  ereport(ERROR,
12582  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
12583  errmsg("cannot move an owned sequence into another schema"),
12584  errdetail("Sequence \"%s\" is linked to table \"%s\".",
12586  get_rel_name(tableId))));
12587  }
12588 
12589  /* Get and lock schema OID and check its permissions. */
12590  newrv = makeRangeVar(stmt->newschema, RelationGetRelationName(rel), -1);
12591  nspOid = RangeVarGetAndCheckCreationNamespace(newrv, NoLock, NULL);
12592 
12593  /* common checks on switching namespaces */
12594  CheckSetNamespace(oldNspOid, nspOid);
12595 
12596  objsMoved = new_object_addresses();
12597  AlterTableNamespaceInternal(rel, oldNspOid, nspOid, objsMoved);
12598  free_object_addresses(objsMoved);
12599 
12600  ObjectAddressSet(myself, RelationRelationId, relid);
12601 
12602  if (oldschema)
12603  *oldschema = oldNspOid;
12604 
12605  /* close rel, but keep lock until commit */
12606  relation_close(rel, NoLock);
12607 
12608  return myself;
12609 }
bool sequenceIsOwned(Oid seqId, char deptype, Oid *tableId, int32 *colId)
Definition: pg_depend.c:500
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, bool missing_ok, bool nowait, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:218
#define RelationRelationId
Definition: pg_class.h:29
int errcode(int sqlerrcode)
Definition: elog.c:575
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1266
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2055
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2326
Form_pg_class rd_rel
Definition: rel.h:114
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:532
signed int int32
Definition: c.h:246
char * relname
Definition: primnodes.h:68
#define ERROR
Definition: elog.h:43
void AlterTableNamespaceInternal(Relation rel, Oid oldNspOid, Oid nspOid, ObjectAddresses *objsMoved)
Definition: tablecmds.c:12617
#define NoLock
Definition: lockdefs.h:34
static void RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg)
Definition: tablecmds.c:13132
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define RelationGetRelationName(relation)
Definition: rel.h:436
#define ereport(elevel, rest)
Definition: elog.h:122
void CheckSetNamespace(Oid oldNspOid, Oid nspOid)
Definition: namespace.c:2928
Oid RangeVarGetAndCheckCreationNamespace(RangeVar *relation, LOCKMODE lockmode, Oid *existing_relation_id)
Definition: namespace.c:508
#define NOTICE
Definition: elog.h:37
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define AccessExclusiveLock
Definition: lockdefs.h:45
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:797
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1120
#define RELKIND_SEQUENCE
Definition: pg_class.h:162
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1726
RangeVar * makeRangeVar(char *schemaname, char *relname, int location)
Definition: makefuncs.c:419
#define RelationGetNamespace(relation)
Definition: rel.h:443
void AlterTableNamespaceInternal ( Relation  rel,
Oid  oldNspOid,
Oid  nspOid,
ObjectAddresses objsMoved 
)

Definition at line 12617 of file tablecmds.c.

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

Referenced by AlterObjectNamespace_oid(), and AlterTableNamespace().

12619 {
12620  Relation classRel;
12621 
12622  Assert(objsMoved != NULL);
12623 
12624  /* OK, modify the pg_class row and pg_depend entry */
12626 
12627  AlterRelationNamespaceInternal(classRel, RelationGetRelid(rel), oldNspOid,
12628  nspOid, true, objsMoved);
12629 
12630  /* Fix the table's row type too */
12631  AlterTypeNamespaceInternal(rel->rd_rel->reltype,
12632  nspOid, false, false, objsMoved);
12633 
12634  /* Fix other dependent stuff */
12635  if (rel->rd_rel->relkind == RELKIND_RELATION ||
12636  rel->rd_rel->relkind == RELKIND_MATVIEW ||
12637  rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
12638  {
12639  AlterIndexNamespaces(classRel, rel, oldNspOid, nspOid, objsMoved);
12640  AlterSeqNamespaces(classRel, rel, oldNspOid, nspOid,
12641  objsMoved, AccessExclusiveLock);
12642  AlterConstraintNamespaces(RelationGetRelid(rel), oldNspOid, nspOid,
12643  false, objsMoved);
12644  }
12645 
12646  heap_close(classRel, RowExclusiveLock);
12647 }
#define RelationRelationId
Definition: pg_class.h:29
#define RELKIND_MATVIEW
Definition: pg_class.h:165
Oid AlterTypeNamespaceInternal(Oid typeOid, Oid nspOid, bool isImplicitArray, bool errorOnTableType, ObjectAddresses *objsMoved)
Definition: typecmds.c:3577
#define heap_close(r, l)
Definition: heapam.h:97
Form_pg_class rd_rel
Definition: rel.h:114
static void AlterIndexNamespaces(Relation classRel, Relation rel, Oid oldNspOid, Oid newNspOid, ObjectAddresses *objsMoved)
Definition: tablecmds.c:12725
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:12770
#define RowExclusiveLock
Definition: lockdefs.h:38
#define RELKIND_PARTITIONED_TABLE
Definition: pg_class.h:168
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define Assert(condition)
Definition: c.h:681
void AlterRelationNamespaceInternal(Relation classRel, Oid relOid, Oid oldNspOid, Oid newNspOid, bool hasDependEntry, ObjectAddresses *objsMoved)
Definition: tablecmds.c:12655
#define AccessExclusiveLock
Definition: lockdefs.h:45
#define RELKIND_RELATION
Definition: pg_class.h:160
#define RelationGetRelid(relation)
Definition: rel.h:416
void AtEOSubXact_on_commit_actions ( bool  isCommit,
SubTransactionId  mySubid,
SubTransactionId  parentSubid 
)

Definition at line 13022 of file tablecmds.c.

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

Referenced by AbortSubTransaction(), and CommitSubTransaction().

13024 {
13025  ListCell *cur_item;
13026  ListCell *prev_item;
13027 
13028  prev_item = NULL;
13029  cur_item = list_head(on_commits);
13030 
13031  while (cur_item != NULL)
13032  {
13033  OnCommitItem *oc = (OnCommitItem *) lfirst(cur_item);
13034 
13035  if (!isCommit && oc->creating_subid == mySubid)
13036  {
13037  /* cur_item must be removed */
13038  on_commits = list_delete_cell(on_commits, cur_item, prev_item);
13039  pfree(oc);
13040  if (prev_item)
13041  cur_item = lnext(prev_item);
13042  else
13043  cur_item = list_head(on_commits);
13044  }
13045  else
13046  {
13047  /* cur_item must be preserved */
13048  if (oc->creating_subid == mySubid)
13049  oc->creating_subid = parentSubid;
13050  if (oc->deleting_subid == mySubid)
13051  oc->deleting_subid = isCommit ? parentSubid : InvalidSubTransactionId;
13052  prev_item = cur_item;
13053  cur_item = lnext(prev_item);
13054  }
13055  }
13056 }
SubTransactionId creating_subid
Definition: tablecmds.c:120
void pfree(void *pointer)
Definition: mcxt.c:949
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 lfirst(lc)
Definition: pg_list.h:106
#define InvalidSubTransactionId
Definition: c.h:397
void AtEOXact_on_commit_actions ( bool  isCommit)

Definition at line 12980 of file tablecmds.c.

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

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

12981 {
12982  ListCell *cur_item;
12983  ListCell *prev_item;
12984 
12985  prev_item = NULL;
12986  cur_item = list_head(on_commits);
12987 
12988  while (cur_item != NULL)
12989  {
12990  OnCommitItem *oc = (OnCommitItem *) lfirst(cur_item);
12991 
12992  if (isCommit ? oc->deleting_subid != InvalidSubTransactionId :
12994  {
12995  /* cur_item must be removed */
12996  on_commits = list_delete_cell(on_commits, cur_item, prev_item);
12997  pfree(oc);
12998  if (prev_item)
12999  cur_item = lnext(prev_item);
13000  else
13001  cur_item = list_head(on_commits);
13002  }
13003  else
13004  {
13005  /* cur_item must be preserved */
13008  prev_item = cur_item;
13009  cur_item = lnext(prev_item);
13010  }
13011  }
13012 }
SubTransactionId creating_subid
Definition: tablecmds.c:120
void pfree(void *pointer)
Definition: mcxt.c:949
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 lfirst(lc)
Definition: pg_list.h:106
#define InvalidSubTransactionId
Definition: c.h:397
void ATExecChangeOwner ( Oid  relationOid,
Oid  newOwnerId,
bool  recursing,
LOCKMODE  lockmode 
)

Definition at line 9922 of file tablecmds.c.

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

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

9923 {
9924  Relation target_rel;
9925  Relation class_rel;
9926  HeapTuple tuple;
9927  Form_pg_class tuple_class;
9928 
9929  /*
9930  * Get exclusive lock till end of transaction on the target table. Use
9931  * relation_open so that we can work on indexes and sequences.
9932  */
9933  target_rel = relation_open(relationOid, lockmode);
9934 
9935  /* Get its pg_class tuple, too */
9937 
9938  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relationOid));
9939  if (!HeapTupleIsValid(tuple))
9940  elog(ERROR, "cache lookup failed for relation %u", relationOid);
9941  tuple_class = (Form_pg_class) GETSTRUCT(tuple);
9942 
9943  /* Can we change the ownership of this tuple? */
9944  switch (tuple_class->relkind)
9945  {
9946  case RELKIND_RELATION:
9947  case RELKIND_VIEW:
9948  case RELKIND_MATVIEW:
9949  case RELKIND_FOREIGN_TABLE:
9951  /* ok to change owner */
9952  break;
9953  case RELKIND_INDEX:
9954  if (!recursing)
9955  {
9956  /*
9957  * Because ALTER INDEX OWNER used to be allowed, and in fact
9958  * is generated by old versions of pg_dump, we give a warning
9959  * and do nothing rather than erroring out. Also, to avoid
9960  * unnecessary chatter while restoring those old dumps, say
9961  * nothing at all if the command would be a no-op anyway.
9962  */
9963  if (tuple_class->relowner != newOwnerId)
9964  ereport(WARNING,
9965  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
9966  errmsg("cannot change owner of index \"%s\"",
9967  NameStr(tuple_class->relname)),
9968  errhint("Change the ownership of the index's table, instead.")));
9969  /* quick hack to exit via the no-op path */
9970  newOwnerId = tuple_class->relowner;
9971  }
9972  break;
9973  case RELKIND_SEQUENCE:
9974  if (!recursing &&
9975  tuple_class->relowner != newOwnerId)
9976  {
9977  /* if it's an owned sequence, disallow changing it by itself */
9978  Oid tableId;
9979  int32 colId;
9980 
9981  if (sequenceIsOwned(relationOid, DEPENDENCY_AUTO, &tableId, &colId) ||
9982  sequenceIsOwned(relationOid, DEPENDENCY_INTERNAL, &tableId, &colId))
9983  ereport(ERROR,
9984  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
9985  errmsg("cannot change owner of sequence \"%s\"",
9986  NameStr(tuple_class->relname)),
9987  errdetail("Sequence \"%s\" is linked to table \"%s\".",
9988  NameStr(tuple_class->relname),
9989  get_rel_name(tableId))));
9990  }
9991  break;
9993  if (recursing)
9994  break;
9995  ereport(ERROR,
9996  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
9997  errmsg("\"%s\" is a composite type",
9998  NameStr(tuple_class->relname)),
9999  errhint("Use ALTER TYPE instead.")));
10000  break;
10001  case RELKIND_TOASTVALUE:
10002  if (recursing)
10003  break;
10004  /* FALL THRU */
10005  default:
10006  ereport(ERROR,
10007  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
10008  errmsg("\"%s\" is not a table, view, sequence, or foreign table",
10009  NameStr(tuple_class->relname))));
10010  }
10011 
10012  /*
10013  * If the new owner is the same as the existing owner, consider the
10014  * command to have succeeded. This is for dump restoration purposes.
10015  */
10016  if (tuple_class->relowner != newOwnerId)
10017  {
10018  Datum repl_val[Natts_pg_class];
10019  bool repl_null[Natts_pg_class];
10020  bool repl_repl[Natts_pg_class];
10021  Acl *newAcl;
10022  Datum aclDatum;
10023  bool isNull;
10024  HeapTuple newtuple;
10025 
10026  /* skip permission checks when recursing to index or toast table */
10027  if (!recursing)
10028  {
10029  /* Superusers can always do it */
10030  if (!superuser())
10031  {
10032  Oid namespaceOid = tuple_class->relnamespace;
10033  AclResult aclresult;
10034 
10035  /* Otherwise, must be owner of the existing object */
10036  if (!pg_class_ownercheck(relationOid, GetUserId()))
10038  RelationGetRelationName(target_rel));
10039 
10040  /* Must be able to become new owner */
10041  check_is_member_of_role(GetUserId(), newOwnerId);
10042 
10043  /* New owner must have CREATE privilege on namespace */
10044  aclresult = pg_namespace_aclcheck(namespaceOid, newOwnerId,
10045  ACL_CREATE);
10046  if (aclresult != ACLCHECK_OK)
10048  get_namespace_name(namespaceOid));
10049  }
10050  }
10051 
10052  memset(repl_null, false, sizeof(repl_null));
10053  memset(repl_repl, false, sizeof(repl_repl));
10054 
10055  repl_repl[Anum_pg_class_relowner - 1] = true;
10056  repl_val[Anum_pg_class_relowner - 1] = ObjectIdGetDatum(newOwnerId);
10057 
10058  /*
10059  * Determine the modified ACL for the new owner. This is only
10060  * necessary when the ACL is non-null.
10061  */
10062  aclDatum = SysCacheGetAttr(RELOID, tuple,
10064  &isNull);
10065  if (!isNull)
10066  {
10067  newAcl = aclnewowner(DatumGetAclP(aclDatum),
10068  tuple_class->relowner, newOwnerId);
10069  repl_repl[Anum_pg_class_relacl - 1] = true;
10070  repl_val[Anum_pg_class_relacl - 1] = PointerGetDatum(newAcl);
10071  }
10072 
10073  newtuple = heap_modify_tuple(tuple, RelationGetDescr(class_rel), repl_val, repl_null, repl_repl);
10074 
10075  CatalogTupleUpdate(class_rel, &newtuple->t_self, newtuple);
10076 
10077  heap_freetuple(newtuple);
10078 
10079  /*
10080  * We must similarly update any per-column ACLs to reflect the new
10081  * owner; for neatness reasons that's split out as a subroutine.
10082  */
10083  change_owner_fix_column_acls(relationOid,
10084  tuple_class->relowner,
10085  newOwnerId);
10086 
10087  /*
10088  * Update owner dependency reference, if any. A composite type has
10089  * none, because it's tracked for the pg_type entry instead of here;
10090  * indexes and TOAST tables don't have their own entries either.
10091  */
10092  if (tuple_class->relkind != RELKIND_COMPOSITE_TYPE &&
10093  tuple_class->relkind != RELKIND_INDEX &&
10094  tuple_class->relkind != RELKIND_TOASTVALUE)
10096  newOwnerId);
10097 
10098  /*
10099  * Also change the ownership of the table's row type, if it has one
10100  */
10101  if (tuple_class->relkind != RELKIND_INDEX)
10102  AlterTypeOwnerInternal(tuple_class->reltype, newOwnerId);
10103 
10104  /*
10105  * If we are operating on a table or materialized view, also change
10106  * the ownership of any indexes and sequences that belong to the
10107  * relation, as well as its toast table (if it has one).
10108  */
10109  if (tuple_class->relkind == RELKIND_RELATION ||
10110  tuple_class->relkind == RELKIND_MATVIEW ||
10111  tuple_class->relkind == RELKIND_TOASTVALUE)
10112  {
10113  List *index_oid_list;
10114  ListCell *i;
10115 
10116  /* Find all the indexes belonging to this relation */
10117  index_oid_list = RelationGetIndexList(target_rel);
10118 
10119  /* For each index, recursively change its ownership */
10120  foreach(i, index_oid_list)
10121  ATExecChangeOwner(lfirst_oid(i), newOwnerId, true, lockmode);
10122 
10123  list_free(index_oid_list);
10124  }
10125 
10126  if (tuple_class->relkind == RELKIND_RELATION ||
10127  tuple_class->relkind == RELKIND_MATVIEW)
10128  {
10129  /* If it has a toast table, recurse to change its ownership */
10130  if (tuple_class->reltoastrelid != InvalidOid)
10131  ATExecChangeOwner(tuple_class->reltoastrelid, newOwnerId,
10132  true, lockmode);
10133 
10134  /* If it has dependent sequences, recurse to change them too */
10135  change_owner_recurse_to_sequences(relationOid, newOwnerId, lockmode);
10136  }
10137  }
10138 
10140 
10141  ReleaseSysCache(tuple);
10142  heap_close(class_rel, RowExclusiveLock);
10143  relation_close(target_rel, NoLock);
10144 }
#define Natts_pg_class
Definition: pg_class.h:102
int errhint(const char *fmt,...)
Definition: elog.c:987
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define Anum_pg_class_relacl
Definition: pg_class.h:133
bool sequenceIsOwned(Oid seqId, char deptype, Oid *tableId, int32 *colId)
Definition: pg_depend.c:500
#define RelationGetDescr(relation)
Definition: rel.h:428
Oid GetUserId(void)
Definition: miscinit.c:284
#define DatumGetAclP(X)
Definition: acl.h:121
#define PointerGetDatum(X)
Definition: postgres.h:562
#define RelationRelationId
Definition: pg_class.h:29
#define RELKIND_MATVIEW
Definition: pg_class.h:165
int errcode(int sqlerrcode)
Definition: elog.c:575
bool superuser(void)
Definition: superuser.c:47
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1266
void AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId)
Definition: typecmds.c:3447
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
unsigned int Oid
Definition: postgres_ext.h:31
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4484
#define RELKIND_COMPOSITE_TYPE
Definition: pg_class.h:166
signed int int32
Definition: c.h:246
void changeDependencyOnOwner(Oid classId, Oid objectId, Oid newOwnerId)
Definition: pg_shdepend.c:304
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define ACL_CREATE
Definition: parsenodes.h:82
ItemPointerData t_self
Definition: htup.h:65
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3033
#define NoLock
Definition: lockdefs.h:34
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3399
#define RowExclusiveLock
Definition: lockdefs.h:38
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define RelationGetRelationName(relation)
Definition: rel.h:436
#define RELKIND_FOREIGN_TABLE
Definition: pg_class.h:167
void check_is_member_of_role(Oid member, Oid role)
Definition: acl.c:4876
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
void ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing, LOCKMODE lockmode)
Definition: tablecmds.c:9922
#define WARNING
Definition: elog.h:40
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
#define RELKIND_PARTITIONED_TABLE
Definition: pg_class.h:168
#define RELKIND_TOASTVALUE
Definition: pg_class.h:163
AclResult
Definition: acl.h:178
uintptr_t Datum
Definition: postgres.h:372
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1368
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
bool pg_class_ownercheck(Oid class_oid, Oid roleid)
Definition: aclchk.c:4546
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
static void change_owner_recurse_to_sequences(Oid relationOid, Oid newOwnerId, LOCKMODE lockmode)
Definition: tablecmds.c:10218
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4357
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:10153
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:493
#define RELKIND_INDEX
Definition: pg_class.h:161
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1120
#define elog
Definition: elog.h:219
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:794
#define RELKIND_RELATION
Definition: pg_class.h:160
#define RELKIND_SEQUENCE
Definition: pg_class.h:162
Definition: pg_list.h:45
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1726
Acl * aclnewowner(const Acl *old_acl, Oid oldOwnerId, Oid newOwnerId)
Definition: acl.c:1052
#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 5096 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().

5097 {
5098  Form_pg_type typ = (Form_pg_type) GETSTRUCT(typetuple);
5099  bool typeOk = false;
5100 
5101  if (typ->typtype == TYPTYPE_COMPOSITE)
5102  {
5103  Relation typeRelation;
5104 
5105  Assert(OidIsValid(typ->typrelid));
5106  typeRelation = relation_open(typ->typrelid, AccessShareLock);
5107  typeOk = (typeRelation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE);
5108 
5109  /*
5110  * Close the parent rel, but keep our AccessShareLock on it until xact
5111  * commit. That will prevent someone else from deleting or ALTERing
5112  * the type before the typed table creation/conversion commits.
5113  */
5114  relation_close(typeRelation, NoLock);
5115  }
5116  if (!typeOk)
5117  ereport(ERROR,
5118  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
5119  errmsg("type %s is not a composite type",
5120  format_type_be(HeapTupleGetOid(typetuple)))));
5121 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define TYPTYPE_COMPOSITE
Definition: pg_type.h:721
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:575
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1266
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
FormData_pg_type * Form_pg_type
Definition: pg_type.h:233
Form_pg_class rd_rel
Definition: rel.h:114
#define OidIsValid(objectId)
Definition: c.h:532
#define RELKIND_COMPOSITE_TYPE
Definition: pg_class.h:166
#define ERROR
Definition: elog.h:43
#define NoLock
Definition: lockdefs.h:34
#define ereport(elevel, rest)
Definition: elog.h:122
#define Assert(condition)
Definition: c.h:681
int errmsg(const char *fmt,...)
Definition: elog.c:797
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1120
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
void CheckTableNotInUse ( Relation  rel,
const char *  stmt 
)

Definition at line 3062 of file tablecmds.c.

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

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

3063 {
3064  int expected_refcnt;
3065 
3066  expected_refcnt = rel->rd_isnailed ? 2 : 1;
3067  if (rel->rd_refcnt != expected_refcnt)
3068  ereport(ERROR,
3069  (errcode(ERRCODE_OBJECT_IN_USE),
3070  /* translator: first %s is a SQL command, eg ALTER TABLE */
3071  errmsg("cannot %s \"%s\" because "
3072  "it is being used by active queries in this session",
3073  stmt, RelationGetRelationName(rel))));
3074 
3075  if (rel->rd_rel->relkind != RELKIND_INDEX &&
3077  ereport(ERROR,
3078  (errcode(ERRCODE_OBJECT_IN_USE),
3079  /* translator: first %s is a SQL command, eg ALTER TABLE */
3080  errmsg("cannot %s \"%s\" because "
3081  "it has pending trigger events",
3082  stmt, RelationGetRelationName(rel))));
3083 }
bool rd_isnailed
Definition: rel.h:91
int errcode(int sqlerrcode)
Definition: elog.c:575
Form_pg_class rd_rel
Definition: rel.h:114
#define ERROR
Definition: elog.h:43
#define RelationGetRelationName(relation)
Definition: rel.h:436
#define ereport(elevel, rest)
Definition: elog.h:122
bool AfterTriggerPendingOnRel(Oid relid)
Definition: trigger.c:5360
int errmsg(const char *fmt,...)
Definition: elog.c:797
int rd_refcnt
Definition: rel.h:88
#define RELKIND_INDEX
Definition: pg_class.h:161
#define RelationGetRelid(relation)
Definition: rel.h:416
ObjectAddress DefineRelation ( CreateStmt stmt,
char  relkind,
Oid  ownerId,
ObjectAddress typaddress,
const char *  queryString 
)

Definition at line 504 of file tablecmds.c.

References AccessExclusiveLock, ACL_CREATE, ACL_KIND_TABLESPACE, ACL_USAGE, aclcheck_error(), aclcheck_error_type(), ACLCHECK_OK, AddRelationNewConstraints(), allowSystemTableMods, Assert, RawColumnDefault::attnum, CookedConstraint::attnum, BuildDescForRelation(), check_default_allows_bound(), 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_default_oid_from_partdesc(), get_tablespace_name(), get_tablespace_oid(), GetDefaultTablespace(), GetUserId(), GLOBALTABLESPACE_OID, heap_close, heap_create_with_catalog(), heap_open(), HEAP_RELOPT_NAMESPACES, heap_reloptions(), ColumnDef::identity, CookedConstraint::inhcount, CreateStmt::inhRelations, InSecurityRestrictedOperation(), interpretOidsOption(), InvalidOid, PartitionBoundSpec::is_default, CookedConstraint::is_local, CookedConstraint::is_no_inherit, lappend(), lfirst, linitial_oid, list_concat(), list_length(), make_parsestate(), MergeAttributes(), MyDatabaseTableSpace, CookedConstraint::name, NAMEDATALEN, NIL, NoLock, ObjectAddressSet, CreateStmt::ofTypename, OidIsValid, CreateStmt::oncommit, ONCOMMIT_NOOP, CreateStmt::options, ParseState::p_sourcetext, palloc(), CreateStmt::partbound, PARTITION_MAX_KEYS, PartitionSpec::partParams, CreateStmt::partspec, pg_tablespace_aclcheck(), pg_type_aclcheck(), RangeVarGetAndCheckCreationNamespace(), RawColumnDefault::raw_default, ColumnDef::raw_default, RelationData::rd_rel, CreateStmt::relation, relation_close(), relation_open(), RelationGetPartitionDesc, RelationGetRelationName, RelationGetRelid, RelationRelationId, RELKIND_PARTITIONED_TABLE, RELKIND_RELATION, RELKIND_VIEW, RangeVar::relname, RangeVar::relpersistence, RELPERSISTENCE_TEMP, CookedConstraint::skip_validation, StoreCatalogInheritance(), StorePartitionBound(), StorePartitionKey(), StrNCpy, CreateStmt::tableElts, CreateStmt::tablespacename, tupleDesc::tdhasoid, transformPartitionBound(), transformPartitionSpec(), transformRelOptions(), TupleDescAttr, typenameTypeId(), update_default_partition_oid(), and view_reloptions().

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

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

References AccessExclusiveLock, ACL_KIND_CLASS, aclcheck_error(), ACLCHECK_NOT_OWNER, AfterTriggerBeginQuery(), AfterTriggerEndQuery(), TruncateStmt::behavior, CheckTableForSerializableConflictIn(), CreateExecutorState(), DROP_CASCADE, DROP_RESTRICT, ereport, errcode(), errhint(), errmsg(), ERROR, EState::es_num_result_relations, EState::es_result_relation_info, EState::es_result_relations, ExecASTruncateTriggers(), ExecBSTruncateTriggers(), find_all_inheritors(), FreeExecutorState(), GetCurrentSubTransactionId(), GetOldestMultiXactId(), getOwnedSequences(), GetUserId(), heap_close, heap_create_init_fork(), heap_open(), heap_openrv(), heap_truncate_check_FKs(), heap_truncate_find_FKs(), heap_truncate_one_rel(), RangeVar::inh, InitResultRelInfo(), lappend(), lappend_oid(), lfirst, lfirst_oid, list_length(), list_member_oid(), NIL, NoLock, NOTICE, 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().

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

Definition at line 4933 of file tablecmds.c.

References AccessShareLock, Anum_pg_depend_refclassid, Anum_pg_depend_refobjid, BTEqualStrategyNumber, check_stack_depth(), DependReferenceIndexId, DependRelationId, ereport, errcode(), errmsg(), ERROR, find_composite_type_dependencies(), GETSTRUCT, heap_open(), HeapTupleIsValid, NameStr, 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(), TupleDescAttr, and TypeRelationId.

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

4935 {
4936  Relation depRel;
4937  ScanKeyData key[2];
4938  SysScanDesc depScan;
4939  HeapTuple depTup;
4940 
4941  /* since this function recurses, it could be driven to stack overflow */
4943 
4944  /*
4945  * We scan pg_depend to find those things that depend on the given type.
4946  * (We assume we can ignore refobjsubid for a type.)
4947  */
4949 
4950  ScanKeyInit(&key[0],
4952  BTEqualStrategyNumber, F_OIDEQ,
4954  ScanKeyInit(&key[1],
4956  BTEqualStrategyNumber, F_OIDEQ,
4957  ObjectIdGetDatum(typeOid));
4958 
4959  depScan = systable_beginscan(depRel, DependReferenceIndexId, true,
4960  NULL, 2, key);
4961 
4962  while (HeapTupleIsValid(depTup = systable_getnext(depScan)))
4963  {
4964  Form_pg_depend pg_depend = (Form_pg_depend) GETSTRUCT(depTup);
4965  Relation rel;
4966  Form_pg_attribute att;
4967 
4968  /* Check for directly dependent types */
4969  if (pg_depend->classid == TypeRelationId)
4970  {
4971  /*
4972  * This must be an array, domain, or range containing the given
4973  * type, so recursively check for uses of this type. Note that
4974  * any error message will mention the original type not the
4975  * container; this is intentional.
4976  */
4977  find_composite_type_dependencies(pg_depend->objid,
4978  origRelation, origTypeName);
4979  continue;
4980  }
4981 
4982  /* Else, ignore dependees that aren't user columns of relations */
4983  /* (we assume system columns are never of interesting types) */
4984  if (pg_depend->classid != RelationRelationId ||
4985  pg_depend->objsubid <= 0)
4986  continue;
4987 
4988  rel = relation_open(pg_depend->objid, AccessShareLock);
4989  att = TupleDescAttr(rel->rd_att, pg_depend->objsubid - 1);
4990 
4991  if (rel->rd_rel->relkind == RELKIND_RELATION ||
4992  rel->rd_rel->relkind == RELKIND_MATVIEW ||
4993  rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
4994  {
4995  if (origTypeName)
4996  ereport(ERROR,
4997  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4998  errmsg("cannot alter type \"%s\" because column \"%s.%s\" uses it",
4999  origTypeName,
5001  NameStr(att->attname))));
5002  else if (origRelation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
5003  ereport(ERROR,
5004  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5005  errmsg("cannot alter type \"%s\" because column \"%s.%s\" uses it",
5006  RelationGetRelationName(origRelation),
5008  NameStr(att->attname))));
5009  else if (origRelation->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
5010  ereport(ERROR,
5011  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5012  errmsg("cannot alter foreign table \"%s\" because column \"%s.%s\" uses its row type",
5013  RelationGetRelationName(origRelation),
5015  NameStr(att->attname))));
5016  else
5017  ereport(ERROR,
5018  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5019  errmsg("cannot alter table \"%s\" because column \"%s.%s\" uses its row type",
5020  RelationGetRelationName(origRelation),
5022  NameStr(att->attname))));
5023  }
5024  else if (OidIsValid(rel->rd_rel->reltype))
5025  {
5026  /*
5027  * A view or composite type itself isn't a problem, but we must
5028  * recursively check for indirect dependencies via its rowtype.
5029  */
5031  origRelation, origTypeName);
5032  }
5033 
5035  }
5036 
5037  systable_endscan(depScan);
5038 
5040 }
#define Anum_pg_depend_refobjid
Definition: pg_depend.h:72
#define Anum_pg_depend_refclassid
Definition: pg_depend.h:71
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:84
#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:4933
#define DependRelationId
Definition: pg_depend.h:29
#define RELKIND_MATVIEW
Definition: pg_class.h:165
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:575
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1266
Form_pg_class rd_rel
Definition: rel.h:114
#define TypeRelationId
Definition: pg_type.h:34
#define OidIsValid(objectId)
Definition: c.h:532
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:328
#define RELKIND_COMPOSITE_TYPE
Definition: pg_class.h:166
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
void check_stack_depth(void)
Definition: postgres.c:3150
#define RelationGetRelationName(relation)
Definition: rel.h:436
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
#define RELKIND_FOREIGN_TABLE
Definition: pg_class.h:167
FormData_pg_depend * Form_pg_depend
Definition: pg_depend.h:61
#define ereport(elevel, rest)
Definition: elog.h:122
#define RELKIND_PARTITIONED_TABLE
Definition: pg_class.h:168
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
TupleDesc rd_att
Definition: rel.h:115
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define NameStr(name)
Definition: c.h:493
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1120
#define RELKIND_RELATION
Definition: pg_class.h:160
#define BTEqualStrategyNumber
Definition: stratnum.h:31
bool PartConstraintImpliedByRelConstraint ( Relation  scanrel,
List partConstraint 
)

Definition at line 13537 of file tablecmds.c.

References NullTest::arg, NullTest::argisrow, canonicalize_qual(), constrCheck::ccbin, constrCheck::ccvalid, tupleConstr::check, eval_const_expressions(), tupleConstr::has_not_null, i, IS_NOT_NULL, lappend(), list_concat(), list_make1, NullTest::location, make_ands_explicit(), make_ands_implicit(), makeNode, makeVar(), tupleDesc::natts, NIL, NullTest::nulltesttype, tupleConstr::num_check, predicate_implied_by(), RelationData::rd_att, RelationGetDescr, stringToNode(), and TupleDescAttr.

Referenced by check_default_allows_bound(), and ValidatePartitionConstraints().

13539 {
13540  List *existConstraint = NIL;
13541  TupleConstr *constr = RelationGetDescr(scanrel)->constr;
13542  int num_check,
13543  i;
13544 
13545  if (constr && constr->has_not_null)
13546  {
13547  int natts = scanrel->rd_att->natts;
13548 
13549  for (i = 1; i <= natts; i++)
13550  {
13551  Form_pg_attribute att = TupleDescAttr(scanrel->rd_att, i - 1);
13552 
13553  if (att->attnotnull && !att->attisdropped)
13554  {
13555  NullTest *ntest = makeNode(NullTest);
13556 
13557  ntest->arg = (Expr *) makeVar(1,
13558  i,
13559  att->atttypid,
13560  att->atttypmod,
13561  att->attcollation,
13562  0);
13563  ntest->nulltesttype = IS_NOT_NULL;
13564 
13565  /*
13566  * argisrow=false is correct even for a composite column,
13567  * because attnotnull does not represent a SQL-spec IS NOT
13568  * NULL test in such a case, just IS DISTINCT FROM NULL.
13569  */
13570  ntest->argisrow = false;
13571  ntest->location = -1;
13572  existConstraint = lappend(existConstraint, ntest);
13573  }
13574  }
13575  }
13576 
13577  num_check = (constr != NULL) ? constr->num_check : 0;
13578  for (i = 0; i < num_check; i++)
13579  {
13580  Node *cexpr;
13581 
13582  /*
13583  * If this constraint hasn't been fully validated yet, we must ignore
13584  * it here.
13585  */
13586  if (!constr->check[i].ccvalid)
13587  continue;
13588 
13589  cexpr = stringToNode(constr->check[i].ccbin);
13590 
13591  /*
13592  * Run each expression through const-simplification and
13593  * canonicalization. It is necessary, because we will be comparing it
13594  * to similarly-processed partition constraint expressions, and may
13595  * fail to detect valid matches without this.
13596  */
13597  cexpr = eval_const_expressions(NULL, cexpr);
13598  cexpr = (Node *) canonicalize_qual((Expr *) cexpr);
13599 
13600  existConstraint = list_concat(existConstraint,
13601  make_ands_implicit((Expr *) cexpr));
13602  }
13603 
13604  if (existConstraint != NIL)
13605  existConstraint = list_make1(make_ands_explicit(existConstraint));
13606 
13607  /* And away we go ... */
13608  return predicate_implied_by(partConstraint, existConstraint, true);
13609 }
#define NIL
Definition: pg_list.h:69
bool predicate_implied_by(List *predicate_list, List *clause_list, bool clause_is_check)
Definition: predtest.c:135
void * stringToNode(char *str)
Definition: read.c:38
#define RelationGetDescr(relation)
Definition: rel.h:428
ConstrCheck * check
Definition: tupdesc.h:40
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:84
char * ccbin
Definition: tupdesc.h:31
Definition: nodes.h:510
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2429
List * list_concat(List *list1, List *list2)
Definition: list.c:321
int natts
Definition: tupdesc.h:73
Expr * make_ands_explicit(List *andclauses)
Definition: clauses.c:367
#define list_make1(x1)
Definition: pg_list.h:139
List * make_ands_implicit(Expr *clause)
Definition: clauses.c:378
Expr * arg
Definition: primnodes.h:1180
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
Var * makeVar(Index varno, AttrNumber varattno, Oid vartype, int32 vartypmod, Oid varcollid, Index varlevelsup)
Definition: makefuncs.c:67
bool has_not_null
Definition: tupdesc.h:43
List * lappend(List *list, void *datum)
Definition: list.c:128
Expr * canonicalize_qual(Expr *qual)
Definition: prepqual.c:286
TupleDesc rd_att
Definition: rel.h:115
NullTestType nulltesttype
Definition: primnodes.h:1181
#define makeNode(_type_)
Definition: nodes.h:558
int location
Definition: primnodes.h:1183
bool ccvalid
Definition: tupdesc.h:32
int i
bool argisrow
Definition: primnodes.h:1182
uint16 num_check
Definition: tupdesc.h:42
Definition: pg_list.h:45
void PreCommit_on_commit_actions ( void  )

Definition at line 12909 of file tablecmds.c.

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

Referenced by CommitTransaction(), and PrepareTransaction().

12910 {
12911  ListCell *l;
12912  List *oids_to_truncate = NIL;
12913 
12914  foreach(l, on_commits)
12915  {
12916  OnCommitItem *oc = (OnCommitItem *) lfirst(l);
12917 
12918  /* Ignore entry if already dropped in this xact */
12920  continue;
12921 
12922  switch (oc->oncommit)
12923  {
12924  case ONCOMMIT_NOOP:
12926  /* Do nothing (there shouldn't be such entries, actually) */
12927  break;
12928  case ONCOMMIT_DELETE_ROWS:
12929 
12930  /*
12931  * If this transaction hasn't accessed any temporary
12932  * relations, we can skip truncating ON COMMIT DELETE ROWS
12933  * tables, as they must still be empty.
12934  */
12936  oids_to_truncate = lappend_oid(oids_to_truncate, oc->relid);
12937  break;
12938  case ONCOMMIT_DROP:
12939  {
12940  ObjectAddress object;
12941 
12942  object.classId = RelationRelationId;
12943  object.objectId = oc->relid;
12944  object.objectSubId = 0;
12945 
12946  /*
12947  * Since this is an automatic drop, rather than one
12948  * directly initiated by the user, we pass the
12949  * PERFORM_DELETION_INTERNAL flag.
12950  */
12951  performDeletion(&object,
12953 
12954  /*
12955  * Note that table deletion will call
12956  * remove_on_commit_action, so the entry should get marked
12957  * as deleted.
12958  */
12960  break;
12961  }
12962  }
12963  }
12964  if (oids_to_truncate != NIL)
12965  {
12966  heap_truncate(oids_to_truncate);
12967  CommandCounterIncrement(); /* XXX needed? */
12968  }
12969 }
#define NIL
Definition: pg_list.h:69
OnCommitAction oncommit
Definition: tablecmds.c:111
#define RelationRelationId
Definition: pg_class.h:29
#define XACT_FLAGS_ACCESSEDTEMPREL
Definition: xact.h:86
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
static List * on_commits
Definition: tablecmds.c:124
void performDeletion(const ObjectAddress *object, DropBehavior behavior, int flags)
Definition: dependency.c:303
int MyXactFlags
Definition: xact.c:118
SubTransactionId deleting_subid
Definition: tablecmds.c:121
void CommandCounterIncrement(void)
Definition: xact.c:915
#define Assert(condition)
Definition: c.h:681
#define lfirst(lc)
Definition: pg_list.h:106
void heap_truncate(List *relids)
Definition: heap.c:2858
#define InvalidSubTransactionId
Definition: c.h:397
Definition: pg_list.h:45
#define PERFORM_DELETION_INTERNAL
Definition: dependency.h:174
void RangeVarCallbackOwnsRelation ( const RangeVar relation,
Oid  relId,
Oid  oldRelId,
void *  noCatalogs 
)

Definition at line 13100 of file tablecmds.c.

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

Referenced by AlterSequence(), and ProcessUtilitySlow().

13102 {
13103  HeapTuple tuple;
13104 
13105  /* Nothing to do if the relation was not found. */
13106  if (!OidIsValid(relId))
13107  return;
13108 
13109  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relId));
13110  if (!HeapTupleIsValid(tuple)) /* should not happen */
13111  elog(ERROR, "cache lookup failed for relation %u", relId);
13112 
13113  if (!pg_class_ownercheck(relId, GetUserId()))
13115  relation->relname);
13116 
13117  if (!allowSystemTableMods &&
13118  IsSystemClass(relId, (Form_pg_class) GETSTRUCT(tuple)))
13119  ereport(ERROR,
13120  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
13121  errmsg("permission denied: \"%s\" is a system catalog",
13122  relation->relname)));
13123 
13124  ReleaseSysCache(tuple);
13125 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
Oid GetUserId(void)
Definition: miscinit.c:284
int errcode(int sqlerrcode)
Definition: elog.c:575
#define OidIsValid(objectId)
Definition: c.h:532
bool IsSystemClass(Oid relid, Form_pg_class reltuple)
Definition: catalog.c:75
char * relname
Definition: primnodes.h:68
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3399
#define ereport(elevel, rest)
Definition: elog.h:122
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
bool allowSystemTableMods
Definition: globals.c:112
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
bool pg_class_ownercheck(Oid class_oid, Oid roleid)
Definition: aclchk.c:4546
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
void RangeVarCallbackOwnsTable ( const RangeVar relation,
Oid  relId,
Oid  oldRelId,
void *  arg 
)

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

13069 {
13070  char relkind;
13071 
13072  /* Nothing to do if the relation was not found. */
13073  if (!OidIsValid(relId))
13074  return;
13075 
13076  /*
13077  * If the relation does exist, check whether it's an index. But note that
13078  * the relation might have been dropped between the time we did the name
13079  * lookup and now. In that case, there's nothing to do.
13080  */
13081  relkind = get_rel_relkind(relId);
13082  if (!relkind)
13083  return;
13084  if (relkind != RELKIND_RELATION && relkind != RELKIND_TOASTVALUE &&
13085  relkind != RELKIND_MATVIEW && relkind != RELKIND_PARTITIONED_TABLE)
13086  ereport(ERROR,
13087  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
13088  errmsg("\"%s\" is not a table or materialized view", relation->relname)));
13089 
13090  /* Check permissions */
13091  if (!pg_class_ownercheck(relId, GetUserId()))
13093 }
Oid GetUserId(void)
Definition: miscinit.c:284
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:1801
#define RELKIND_MATVIEW
Definition: pg_class.h:165
int errcode(int sqlerrcode)
Definition: elog.c:575
#define OidIsValid(objectId)
Definition: c.h:532
char * relname
Definition: primnodes.h:68
#define ERROR
Definition: elog.h:43
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3399
#define ereport(elevel, rest)
Definition: elog.h:122
#define RELKIND_PARTITIONED_TABLE
Definition: pg_class.h:168
#define RELKIND_TOASTVALUE
Definition: pg_class.h:163
bool pg_class_ownercheck(Oid class_oid, Oid roleid)
Definition: aclchk.c:4546
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define RELKIND_RELATION
Definition: pg_class.h:160
void register_on_commit_action ( Oid  relid,
OnCommitAction  action 
)

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

12856 {
12857  OnCommitItem *oc;
12858  MemoryContext oldcxt;
12859 
12860  /*
12861  * We needn't bother registering the relation unless there is an ON COMMIT
12862  * action we need to take.
12863  */
12864  if (action == ONCOMMIT_NOOP || action == ONCOMMIT_PRESERVE_ROWS)
12865  return;
12866 
12868 
12869  oc = (OnCommitItem *) palloc(sizeof(OnCommitItem));
12870  oc->relid = relid;
12871  oc->oncommit = action;
12874 
12875  on_commits = lcons(oc, on_commits);
12876 
12877  MemoryContextSwitchTo(oldcxt);
12878 }
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:642
#define InvalidSubTransactionId
Definition: c.h:397
void * palloc(Size size)
Definition: mcxt.c:848
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
void remove_on_commit_action ( Oid  relid)

Definition at line 12886 of file tablecmds.c.

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

Referenced by heap_drop_with_catalog().

12887 {
12888  ListCell *l;
12889 
12890  foreach(l, on_commits)
12891  {
12892  OnCommitItem *oc = (OnCommitItem *) lfirst(l);
12893 
12894  if (oc->relid == relid)
12895  {
12897  break;
12898  }
12899  }
12900 }
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:642
void RemoveRelations ( DropStmt drop)

Definition at line 1006 of file tablecmds.c.

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

Referenced by ExecDropStmt().

1007 {
1008  ObjectAddresses *objects;
1009  char relkind;
1010  ListCell *cell;
1011  int flags = 0;
1012  LOCKMODE lockmode = AccessExclusiveLock;
1013 
1014  /* DROP CONCURRENTLY uses a weaker lock, and has some restrictions */
1015  if (drop->concurrent)
1016  {
1018  lockmode = ShareUpdateExclusiveLock;
1019  Assert(drop->removeType == OBJECT_INDEX);
1020  if (list_length(drop->objects) != 1)
1021  ereport(ERROR,
1022  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1023  errmsg("DROP INDEX CONCURRENTLY does not support dropping multiple objects")));
1024  if (drop->behavior == DROP_CASCADE)
1025  ereport(ERROR,
1026  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1027  errmsg("DROP INDEX CONCURRENTLY does not support CASCADE")));
1028  }
1029 
1030  /*
1031  * First we identify all the relations, then we delete them in a single
1032  * performMultipleDeletions() call. This is to avoid unwanted DROP
1033  * RESTRICT errors if one of the relations depends on another.
1034  */
1035 
1036  /* Determine required relkind */
1037  switch (drop->removeType)
1038  {
1039  case OBJECT_TABLE:
1040  relkind = RELKIND_RELATION;
1041  break;
1042 
1043  case OBJECT_INDEX:
1044  relkind = RELKIND_INDEX;
1045  break;
1046 
1047  case OBJECT_SEQUENCE:
1048  relkind = RELKIND_SEQUENCE;
1049  break;
1050 
1051  case OBJECT_VIEW:
1052  relkind = RELKIND_VIEW;
1053  break;
1054 
1055  case OBJECT_MATVIEW:
1056  relkind = RELKIND_MATVIEW;
1057  break;
1058 
1059  case OBJECT_FOREIGN_TABLE:
1060  relkind = RELKIND_FOREIGN_TABLE;
1061  break;
1062 
1063  default:
1064  elog(ERROR, "unrecognized drop object type: %d",
1065  (int) drop->removeType);
1066  relkind = 0; /* keep compiler quiet */
1067  break;
1068  }
1069 
1070  /* Lock and validate each relation; build a list of object addresses */
1071  objects = new_object_addresses();
1072 
1073  foreach(cell, drop->objects)
1074  {
1075  RangeVar *rel = makeRangeVarFromNameList((List *) lfirst(cell));
1076  Oid relOid;
1077  ObjectAddress obj;
1079 
1080  /*
1081  * These next few steps are a great deal like relation_openrv, but we
1082  * don't bother building a relcache entry since we don't need it.
1083  *
1084  * Check for shared-cache-inval messages before trying to access the
1085  * relation. This is needed to cover the case where the name
1086  * identifies a rel that has been dropped and recreated since the
1087  * start of our transaction: if we don't flush the old syscache entry,
1088  * then we'll latch onto that entry and suffer an error later.
1089  */
1091 
1092  /* Look up the appropriate relation using namespace search. */
1093  state.relkind = relkind;
1094  state.heapOid = InvalidOid;
1095  state.partParentOid = InvalidOid;
1096  state.concurrent = drop->concurrent;
1097  relOid = RangeVarGetRelidExtended(rel, lockmode, true,
1098  false,
1100  (void *) &state);
1101 
1102  /* Not there? */
1103  if (!OidIsValid(relOid))
1104  {
1105  DropErrorMsgNonExistent(rel, relkind, drop->missing_ok);
1106  continue;
1107  }
1108 
1109  /* OK, we're ready to delete this one */
1111  obj.objectId = relOid;
1112  obj.objectSubId = 0;
1113 
1114  add_exact_object_address(&obj, objects);
1115  }
1116 
1117  performMultipleDeletions(objects, drop->behavior, flags);
1118 
1119  free_object_addresses(objects);
1120 }
void AcceptInvalidationMessages(void)
Definition: inval.c:679
int LOCKMODE
Definition: lockdefs.h:26
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, bool missing_ok, bool nowait, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:218
#define RelationRelationId
Definition: pg_class.h:29
List * objects
Definition: parsenodes.h:2578
bool missing_ok
Definition: parsenodes.h:2581
#define RELKIND_MATVIEW
Definition: pg_class.h:165
int errcode(int sqlerrcode)
Definition: elog.c:575
RangeVar * makeRangeVarFromNameList(List *names)
Definition: namespace.c:3023
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2110
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2055
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2326
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:532
ObjectType removeType
Definition: parsenodes.h:2579
#define PERFORM_DELETION_CONCURRENTLY
Definition: dependency.h:175
#define ERROR
Definition: elog.h:43
bool concurrent
Definition: parsenodes.h:2582
DropBehavior behavior
Definition: parsenodes.h:2580
#define RELKIND_FOREIGN_TABLE
Definition: pg_class.h:167
#define ereport(elevel, rest)
Definition: elog.h:122
static void RangeVarCallbackForDropRelation(const RangeVar *rel, Oid relOid, Oid oldRelOid, void *arg)
Definition: tablecmds.c:1129
#define InvalidOid
Definition: postgres_ext.h:36
#define ShareUpdateExclusiveLock
Definition: lockdefs.h:39
#define Assert(condition)
Definition: c.h:681
#define lfirst(lc)
Definition: pg_list.h:106
Definition: regguts.h:298
static int list_length(const List *l)
Definition: pg_list.h:89
#define AccessExclusiveLock
Definition: lockdefs.h:45
static void DropErrorMsgNonExistent(RangeVar *rel, char rightkind, bool missing_ok)
Definition: tablecmds.c:931
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define RELKIND_VIEW
Definition: pg_class.h:164
#define RELKIND_INDEX
Definition: pg_class.h:161
void performMultipleDeletions(const ObjectAddresses *objects, DropBehavior behavior, int flags)
Definition: dependency.c:362
#define elog
Definition: elog.h:219
#define RELKIND_RELATION
Definition: pg_class.h:160
#define RELKIND_SEQUENCE
Definition: pg_class.h:162
Definition: pg_list.h:45
ObjectAddress renameatt ( RenameStmt stmt)

Definition at line 2734 of file tablecmds.c.

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

Referenced by ExecRenameStmt().

2735 {
2736  Oid relid;
2737  AttrNumber attnum;
2738  ObjectAddress address;
2739 
2740  /* lock level taken here should match renameatt_internal */
2742  stmt->missing_ok, false,
2744  NULL);
2745 
2746  if (!OidIsValid(relid))
2747  {
2748  ereport(NOTICE,
2749  (errmsg("relation \"%s\" does not exist, skipping",
2750  stmt->relation->relname)));
2751  return InvalidObjectAddress;
2752  }
2753 
2754  attnum =
2755  renameatt_internal(relid,
2756  stmt->subname, /* old att name */
2757  stmt->newname, /* new att name */
2758  stmt->relation->inh, /* recursive? */
2759  false, /* recursing? */
2760  0, /* expected inhcount */
2761  stmt->behavior);
2762 
2763  ObjectAddressSubSet(address, RelationRelationId, relid, attnum);
2764 
2765  return address;
2766 }
char * subname
Definition: parsenodes.h:2806
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, bool missing_ok, bool nowait, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:218
#define RelationRelationId
Definition: pg_class.h:29
char * newname
Definition: parsenodes.h:2808
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:532
char * relname
Definition: primnodes.h:68
bool missing_ok
Definition: parsenodes.h:2810
#define ereport(elevel, rest)
Definition: elog.h:122
bool inh
Definition: primnodes.h:69
RangeVar * relation
Definition: parsenodes.h:2804
#define NOTICE
Definition: elog.h:37
static void RangeVarCallbackForRenameAttribute(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg)
Definition: tablecmds.c:2714
static AttrNumber renameatt_internal(Oid myrelid, const char *oldattname, const char *newattname, bool recurse, bool recursing, int expected_parents, DropBehavior behavior)
Definition: tablecmds.c:2569
#define ObjectAddressSubSet(addr, class_id, object_id, object_sub_id)
Definition: objectaddress.h:33
#define AccessExclusiveLock
Definition: lockdefs.h:45
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:797
DropBehavior behavior
Definition: parsenodes.h:2809
int16 AttrNumber
Definition: attnum.h:21
ObjectAddress renameatt_type ( RenameStmt stmt)
ObjectAddress RenameConstraint ( RenameStmt stmt)

Definition at line 2871 of file tablecmds.c.

References AccessExclusiveLock, castNode, checkDomainOwner(), elog, ereport, errmsg(), ERROR, heap_close, heap_open(), HeapTupleIsValid, RangeVar::inh, InvalidObjectAddress, InvalidOid, makeTypeNameFromNameList(), RenameStmt::missing_ok, RenameStmt::newname, NoLock, NOTICE, 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().

2872 {
2873  Oid relid = InvalidOid;
2874  Oid typid = InvalidOid;
2875 
2876  if (stmt->renameType == OBJECT_DOMCONSTRAINT)
2877  {
2878  Relation rel;
2879  HeapTuple tup;
2880 
2883  tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2884  if (!HeapTupleIsValid(tup))
2885  elog(ERROR, "cache lookup failed for type %u", typid);
2886  checkDomainOwner(tup);
2887  ReleaseSysCache(tup);
2888  heap_close(rel, NoLock);
2889  }
2890  else
2891  {
2892  /* lock level taken here should match rename_constraint_internal */
2894  stmt->missing_ok, false,
2896  NULL);
2897  if (!OidIsValid(relid))
2898  {
2899  ereport(NOTICE,
2900  (errmsg("relation \"%s\" does not exist, skipping",
2901  stmt->relation->relname)));
2902  return InvalidObjectAddress;
2903  }
2904  }
2905 
2906  return
2907  rename_constraint_internal(relid, typid,
2908  stmt->subname,
2909  stmt->newname,
2910  (stmt->relation &&
2911  stmt->relation->inh), /* recursive? */
2912  false, /* recursing? */
2913  0 /* expected inhcount */ );
2914 
2915 }
char * subname
Definition: parsenodes.h:2806
ObjectType renameType
Definition: parsenodes.h:2802
#define castNode(_type_, nodeptr)
Definition: nodes.h:579
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, bool missing_ok, bool nowait, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:218
#define heap_close(r, l)
Definition: heapam.h:97
static ObjectAddress rename_constraint_internal(Oid myrelid, Oid mytypid, const char *oldconname, const char *newconname, bool recurse, bool recursing, int expected_parents)
Definition: tablecmds.c:2772
char * newname
Definition: parsenodes.h:2808
unsigned int Oid
Definition: postgres_ext.h:31
#define TypeRelationId
Definition: pg_type.h:34
#define OidIsValid(objectId)
Definition: c.h:532
char * relname
Definition: primnodes.h:68
bool missing_ok
Definition: parsenodes.h:2810
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
Node * object
Definition: parsenodes.h:2805
#define ereport(elevel, rest)
Definition: elog.h:122
bool inh
Definition: primnodes.h:69
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
RangeVar * relation
Definition: parsenodes.h:2804
#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:2714
void checkDomainOwner(HeapTuple tup)
Definition: typecmds.c:3038
#define AccessExclusiveLock
Definition: lockdefs.h:45
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:797
TypeName * makeTypeNameFromNameList(List *names)
Definition: makefuncs.c:453
#define elog
Definition: elog.h:219
Definition: pg_list.h:45
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:274
ObjectAddress RenameRelation ( RenameStmt stmt)

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

2923 {
2924  Oid relid;
2925  ObjectAddress address;
2926 
2927  /*
2928  * Grab an exclusive lock on the target table, index, sequence, view,
2929  * materialized view, or foreign table, which we will NOT release until
2930  * end of transaction.
2931  *
2932  * Lock level used here should match RenameRelationInternal, to avoid lock
2933  * escalation.
2934  */
2936  stmt->missing_ok, false,
2938  (void *) stmt);
2939 
2940  if (!OidIsValid(relid))
2941  {
2942  ereport(NOTICE,
2943  (errmsg("relation \"%s\" does not exist, skipping",
2944  stmt->relation->relname)));
2945  return InvalidObjectAddress;
2946  }
2947 
2948  /* Do the work */
2949  RenameRelationInternal(relid, stmt->newname, false);
2950 
2951  ObjectAddressSet(address, RelationRelationId, relid);
2952 
2953  return address;
2954 }
void RenameRelationInternal(Oid myrelid, const char *newrelname, bool is_internal)
Definition: tablecmds.c:2966
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, bool missing_ok, bool nowait, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:218
#define RelationRelationId
Definition: pg_class.h:29
char * newname
Definition: parsenodes.h:2808
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:532
char * relname
Definition: primnodes.h:68
bool missing_ok
Definition: parsenodes.h:2810
static void RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg)
Definition: tablecmds.c:13132
#define ereport(elevel, rest)
Definition: elog.h:122
RangeVar * relation
Definition: parsenodes.h:2804
#define NOTICE
Definition: elog.h:37
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define AccessExclusiveLock
Definition: lockdefs.h:45
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:797
void RenameRelationInternal ( Oid  myrelid,
const char *  newrelname,
bool  is_internal 
)

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

2967 {
2968  Relation targetrelation;
2969  Relation relrelation; /* for RELATION relation */
2970  HeapTuple reltup;
2971  Form_pg_class relform;
2972  Oid namespaceId;
2973 
2974  /*
2975  * Grab an exclusive lock on the target table, index, sequence, view,
2976  * materialized view, or foreign table, which we will NOT release until
2977  * end of transaction.
2978  */
2979  targetrelation = relation_open(myrelid, AccessExclusiveLock);
2980  namespaceId = RelationGetNamespace(targetrelation);
2981 
2982  /*
2983  * Find relation's pg_class tuple, and make sure newrelname isn't in use.
2984  */
2986 
2987  reltup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(myrelid));
2988  if (!HeapTupleIsValid(reltup)) /* shouldn't happen */
2989  elog(ERROR, "cache lookup failed for relation %u", myrelid);
2990  relform = (Form_pg_class) GETSTRUCT(reltup);
2991 
2992  if (get_relname_relid(newrelname, namespaceId) != InvalidOid)
2993  ereport(ERROR,
2994  (errcode(ERRCODE_DUPLICATE_TABLE),
2995  errmsg("relation \"%s\" already exists",
2996  newrelname)));
2997 
2998  /*
2999  * Update pg_class tuple with new relname. (Scribbling on reltup is OK
3000  * because it's a copy...)
3001  */
3002  namestrcpy(&(relform->relname), newrelname);
3003 
3004  CatalogTupleUpdate(relrelation, &reltup->t_self, reltup);
3005 
3007  InvalidOid, is_internal);
3008 
3009  heap_freetuple(reltup);
3010  heap_close(relrelation, RowExclusiveLock);
3011 
3012  /*
3013  * Also rename the associated type, if any.
3014  */
3015  if (OidIsValid(targetrelation->rd_rel->reltype))
3016  RenameTypeInternal(targetrelation->rd_rel->reltype,
3017  newrelname, namespaceId);
3018 
3019  /*
3020  * Also rename the associated constraint, if any.
3021  */
3022  if (targetrelation->rd_rel->relkind == RELKIND_INDEX)
3023  {
3024  Oid constraintId = get_index_constraint(myrelid);
3025 
3026  if (OidIsValid(constraintId))
3027  RenameConstraintById(constraintId, newrelname);
3028  }
3029 
3030  /*
3031  * Close rel, but keep exclusive lock!
3032  */
3033  relation_close(targetrelation, NoLock);
3034 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define RelationRelationId
Definition: pg_class.h:29
int errcode(int sqlerrcode)
Definition: elog.c:575
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1266
#define heap_close(r, l)
Definition: heapam.h:97
Form_pg_class rd_rel
Definition: rel.h:114
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
unsigned int Oid
Definition: postgres_ext.h:31
int namestrcpy(Name name, const char *str)
Definition: name.c:216
#define OidIsValid(objectId)
Definition: c.h:532
void RenameConstraintById(Oid conId, const char *newname)
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
Oid get_relname_relid(const char *relname, Oid relnamespace)
Definition: lsyscache.c:1683
#define NoLock
Definition: lockdefs.h:34
#define InvokeObjectPostAlterHookArg(classId, objectId, subId,auxiliaryId, is_internal)
Definition: objectaccess.h:166
#define RowExclusiveLock
Definition: lockdefs.h:38
Oid get_index_constraint(Oid indexId)
Definition: pg_depend.c:684
#define ereport(elevel, rest)
Definition: elog.h:122
void RenameTypeInternal(Oid typeOid, const char *newTypeName, Oid typeNamespace)
Definition: pg_type.c:692
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:173
#define AccessExclusiveLock
Definition: lockdefs.h:45
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define RELKIND_INDEX
Definition: pg_class.h:161
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1120
#define elog
Definition: elog.h:219
#define RelationGetNamespace(relation)
Definition: rel.h:443
void SetRelationHasSubclass ( Oid  relationId,
bool  relhassubclass 
)

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

2489 {
2490  Relation relationRelation;
2491  HeapTuple tuple;
2492  Form_pg_class classtuple;
2493 
2494  /*
2495  * Fetch a modifiable copy of the tuple, modify it, update pg_class.
2496  */
2497  relationRelation = heap_open(RelationRelationId, RowExclusiveLock);
2498  tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relationId));
2499  if (!HeapTupleIsValid(tuple))
2500  elog(ERROR, "cache lookup failed for relation %u", relationId);
2501  classtuple = (Form_pg_class) GETSTRUCT(tuple);
2502 
2503  if (classtuple->relhassubclass != relhassubclass)
2504  {
2505  classtuple->relhassubclass = relhassubclass;
2506  CatalogTupleUpdate(relationRelation, &tuple->t_self, tuple);
2507  }
2508  else
2509  {
2510  /* no need to change tuple, but force relcache rebuild anyway */
2512  }
2513 
2514  heap_freetuple(tuple);
2515  heap_close(relationRelation, RowExclusiveLock);
2516 }
#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:1373
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:173
void CacheInvalidateRelcacheByTuple(HeapTuple classTuple)
Definition: inval.c:1269
#define elog
Definition: elog.h:219