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

Go to the source code of this file.

Functions

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

Function Documentation

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

Definition at line 11373 of file tablecmds.c.

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

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

11377 {
11378  HeapTuple classTup;
11379  Form_pg_class classForm;
11380  ObjectAddress thisobj;
11381 
11382  classTup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relOid));
11383  if (!HeapTupleIsValid(classTup))
11384  elog(ERROR, "cache lookup failed for relation %u", relOid);
11385  classForm = (Form_pg_class) GETSTRUCT(classTup);
11386 
11387  Assert(classForm->relnamespace == oldNspOid);
11388 
11389  thisobj.classId = RelationRelationId;
11390  thisobj.objectId = relOid;
11391  thisobj.objectSubId = 0;
11392 
11393  /*
11394  * Do nothing when there's nothing to do.
11395  */
11396  if (!object_address_present(&thisobj, objsMoved))
11397  {
11398  /* check for duplicate name (more friendly than unique-index failure) */
11399  if (get_relname_relid(NameStr(classForm->relname),
11400  newNspOid) != InvalidOid)
11401  ereport(ERROR,
11402  (errcode(ERRCODE_DUPLICATE_TABLE),
11403  errmsg("relation \"%s\" already exists in schema \"%s\"",
11404  NameStr(classForm->relname),
11405  get_namespace_name(newNspOid))));
11406 
11407  /* classTup is a copy, so OK to scribble on */
11408  classForm->relnamespace = newNspOid;
11409 
11410  simple_heap_update(classRel, &classTup->t_self, classTup);
11411  CatalogUpdateIndexes(classRel, classTup);
11412 
11413  /* Update dependency on schema if caller said so */
11414  if (hasDependEntry &&
11416  relOid,
11418  oldNspOid,
11419  newNspOid) != 1)
11420  elog(ERROR, "failed to change schema dependency for relation \"%s\"",
11421  NameStr(classForm->relname));
11422 
11423  add_exact_object_address(&thisobj, objsMoved);
11424 
11426  }
11427 
11428  heap_freetuple(classTup);
11429 }
#define NamespaceRelationId
Definition: pg_namespace.h:34
#define GETSTRUCT(TUP)
Definition: htup_details.h:631
#define RelationRelationId
Definition: pg_class.h:29
bool object_address_present(const ObjectAddress *object, const ObjectAddresses *addrs)
Definition: dependency.c:2137
int errcode(int sqlerrcode)
Definition: elog.c:573
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2077
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1306
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:41
ItemPointerData t_self
Definition: htup.h:65
Oid get_relname_relid(const char *relname, Oid relnamespace)
Definition: lsyscache.c:1627
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:2960
#define ereport(elevel, rest)
Definition: elog.h:132
#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:656
void CatalogUpdateIndexes(Relation heapRel, HeapTuple heapTuple)
Definition: indexing.c:157
void simple_heap_update(Relation relation, ItemPointer otid, HeapTuple tup)
Definition: heapam.c:4148
FormData_pg_class * Form_pg_class
Definition: pg_class.h:91
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:150
int errmsg(const char *fmt,...)
Definition: elog.c:795
long changeDependencyFor(Oid classId, Oid objectId, Oid refClassId, Oid oldRefObjectId, Oid newRefObjectId)
Definition: pg_depend.c:297
#define NameStr(name)
Definition: c.h:483
#define elog
Definition: elog.h:228
void AlterTable ( Oid  relid,
LOCKMODE  lockmode,
AlterTableStmt stmt 
)

Definition at line 2762 of file tablecmds.c.

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

Referenced by ProcessUtilitySlow().

2763 {
2764  Relation rel;
2765 
2766  /* Caller is required to provide an adequate lock. */
2767  rel = relation_open(relid, NoLock);
2768 
2769  CheckTableNotInUse(rel, "ALTER TABLE");
2770 
2771  ATController(stmt,
2772  rel, stmt->cmds, interpretInhOption(stmt->relation->inhOpt),
2773  lockmode);
2774 }
InhOption inhOpt
Definition: primnodes.h:75
static void ATController(AlterTableStmt *parsetree, Relation rel, List *cmds, bool recurse, LOCKMODE lockmode)
Definition: tablecmds.c:3072
bool interpretInhOption(InhOption inhOpt)
Definition: parse_clause.c:238
#define NoLock
Definition: lockdefs.h:34
void CheckTableNotInUse(Relation rel, const char *stmt)
Definition: tablecmds.c:2683
RangeVar * relation
Definition: parsenodes.h:1450
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1052
LOCKMODE AlterTableGetLockLevel ( List cmds)

Definition at line 2833 of file tablecmds.c.

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

Referenced by AlterTableInternal(), and ProcessUtilitySlow().

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

Definition at line 2788 of file tablecmds.c.

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

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

2789 {
2790  Relation rel;
2791  LOCKMODE lockmode = AlterTableGetLockLevel(cmds);
2792 
2793  rel = relation_open(relid, lockmode);
2794 
2796 
2797  ATController(NULL, rel, cmds, recurse, lockmode);
2798 }
int LOCKMODE
Definition: lockdefs.h:26
static void ATController(AlterTableStmt *parsetree, Relation rel, List *cmds, bool recurse, LOCKMODE lockmode)
Definition: tablecmds.c:3072
LOCKMODE AlterTableGetLockLevel(List *cmds)
Definition: tablecmds.c:2833
#define NULL
Definition: c.h:215
void EventTriggerAlterTableRelid(Oid objectId)
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1052
Oid AlterTableLookupRelation ( AlterTableStmt stmt,
LOCKMODE  lockmode 
)

Definition at line 2712 of file tablecmds.c.

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

Referenced by ProcessUtilitySlow().

2713 {
2714  return RangeVarGetRelidExtended(stmt->relation, lockmode, stmt->missing_ok, false,
2716  (void *) stmt);
2717 }
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, bool missing_ok, bool nowait, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:232
static void RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg)
Definition: tablecmds.c:11845
RangeVar * relation
Definition: parsenodes.h:1450
Oid AlterTableMoveAll ( AlterTableMoveAllStmt stmt)

Definition at line 9677 of file tablecmds.c.

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

Referenced by ProcessUtilitySlow().

9678 {
9679  List *relations = NIL;
9680  ListCell *l;
9681  ScanKeyData key[1];
9682  Relation rel;
9683  HeapScanDesc scan;
9684  HeapTuple tuple;
9685  Oid orig_tablespaceoid;
9686  Oid new_tablespaceoid;
9687  List *role_oids = roleSpecsToIds(stmt->roles);
9688 
9689  /* Ensure we were not asked to move something we can't */
9690  if (stmt->objtype != OBJECT_TABLE && stmt->objtype != OBJECT_INDEX &&
9691  stmt->objtype != OBJECT_MATVIEW)
9692  ereport(ERROR,
9693  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
9694  errmsg("only tables, indexes, and materialized views exist in tablespaces")));
9695 
9696  /* Get the orig and new tablespace OIDs */
9697  orig_tablespaceoid = get_tablespace_oid(stmt->orig_tablespacename, false);
9698  new_tablespaceoid = get_tablespace_oid(stmt->new_tablespacename, false);
9699 
9700  /* Can't move shared relations in to or out of pg_global */
9701  /* This is also checked by ATExecSetTableSpace, but nice to stop earlier */
9702  if (orig_tablespaceoid == GLOBALTABLESPACE_OID ||
9703  new_tablespaceoid == GLOBALTABLESPACE_OID)
9704  ereport(ERROR,
9705  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
9706  errmsg("cannot move relations in to or out of pg_global tablespace")));
9707 
9708  /*
9709  * Must have CREATE rights on the new tablespace, unless it is the
9710  * database default tablespace (which all users implicitly have CREATE
9711  * rights on).
9712  */
9713  if (OidIsValid(new_tablespaceoid) && new_tablespaceoid != MyDatabaseTableSpace)
9714  {
9715  AclResult aclresult;
9716 
9717  aclresult = pg_tablespace_aclcheck(new_tablespaceoid, GetUserId(),
9718  ACL_CREATE);
9719  if (aclresult != ACLCHECK_OK)
9721  get_tablespace_name(new_tablespaceoid));
9722  }
9723 
9724  /*
9725  * Now that the checks are done, check if we should set either to
9726  * InvalidOid because it is our database's default tablespace.
9727  */
9728  if (orig_tablespaceoid == MyDatabaseTableSpace)
9729  orig_tablespaceoid = InvalidOid;
9730 
9731  if (new_tablespaceoid == MyDatabaseTableSpace)
9732  new_tablespaceoid = InvalidOid;
9733 
9734  /* no-op */
9735  if (orig_tablespaceoid == new_tablespaceoid)
9736  return new_tablespaceoid;
9737 
9738  /*
9739  * Walk the list of objects in the tablespace and move them. This will
9740  * only find objects in our database, of course.
9741  */
9742  ScanKeyInit(&key[0],
9744  BTEqualStrategyNumber, F_OIDEQ,
9745  ObjectIdGetDatum(orig_tablespaceoid));
9746 
9748  scan = heap_beginscan_catalog(rel, 1, key);
9749  while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
9750  {
9751  Oid relOid = HeapTupleGetOid(tuple);
9752  Form_pg_class relForm;
9753 
9754  relForm = (Form_pg_class) GETSTRUCT(tuple);
9755 
9756  /*
9757  * Do not move objects in pg_catalog as part of this, if an admin
9758  * really wishes to do so, they can issue the individual ALTER
9759  * commands directly.
9760  *
9761  * Also, explicitly avoid any shared tables, temp tables, or TOAST
9762  * (TOAST will be moved with the main table).
9763  */
9764  if (IsSystemNamespace(relForm->relnamespace) || relForm->relisshared ||
9765  isAnyTempNamespace(relForm->relnamespace) ||
9766  relForm->relnamespace == PG_TOAST_NAMESPACE)
9767  continue;
9768 
9769  /* Only move the object type requested */
9770  if ((stmt->objtype == OBJECT_TABLE &&
9771  relForm->relkind != RELKIND_RELATION) ||
9772  (stmt->objtype == OBJECT_INDEX &&
9773  relForm->relkind != RELKIND_INDEX) ||
9774  (stmt->objtype == OBJECT_MATVIEW &&
9775  relForm->relkind != RELKIND_MATVIEW))
9776  continue;
9777 
9778  /* Check if we are only moving objects owned by certain roles */
9779  if (role_oids != NIL && !list_member_oid(role_oids, relForm->relowner))
9780  continue;
9781 
9782  /*
9783  * Handle permissions-checking here since we are locking the tables
9784  * and also to avoid doing a bunch of work only to fail part-way. Note
9785  * that permissions will also be checked by AlterTableInternal().
9786  *
9787  * Caller must be considered an owner on the table to move it.
9788  */
9789  if (!pg_class_ownercheck(relOid, GetUserId()))
9791  NameStr(relForm->relname));
9792 
9793  if (stmt->nowait &&
9795  ereport(ERROR,
9796  (errcode(ERRCODE_OBJECT_IN_USE),
9797  errmsg("aborting because lock on relation \"%s\".\"%s\" is not available",
9798  get_namespace_name(relForm->relnamespace),
9799  NameStr(relForm->relname))));
9800  else
9802 
9803  /* Add to our list of objects to move */
9804  relations = lappend_oid(relations, relOid);
9805  }
9806 
9807  heap_endscan(scan);
9809 
9810  if (relations == NIL)
9811  ereport(NOTICE,
9812  (errcode(ERRCODE_NO_DATA_FOUND),
9813  errmsg("no matching relations in tablespace \"%s\" found",
9814  orig_tablespaceoid == InvalidOid ? "(database default)" :
9815  get_tablespace_name(orig_tablespaceoid))));
9816 
9817  /* Everything is locked, loop through and move all of the relations. */
9818  foreach(l, relations)
9819  {
9820  List *cmds = NIL;
9822 
9823  cmd->subtype = AT_SetTableSpace;
9824  cmd->name = stmt->new_tablespacename;
9825 
9826  cmds = lappend(cmds, cmd);
9827 
9829  /* OID is set by AlterTableInternal */
9830  AlterTableInternal(lfirst_oid(l), cmds, false);
9832  }
9833 
9834  return new_tablespaceoid;
9835 }
#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:1370
AclResult pg_tablespace_aclcheck(Oid spc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4439
#define GETSTRUCT(TUP)
Definition: htup_details.h:631
void heap_endscan(HeapScanDesc scan)
Definition: heapam.c:1507
Oid GetUserId(void)
Definition: miscinit.c:274
#define RelationRelationId
Definition: pg_class.h:29
#define Anum_pg_class_reltablespace
Definition: pg_class.h:106
#define RELKIND_MATVIEW
Definition: pg_class.h:160
#define AccessShareLock
Definition: lockdefs.h:36
#define GLOBALTABLESPACE_OID
Definition: pg_tablespace.h:64
Definition: nodes.h:464
int errcode(int sqlerrcode)
Definition: elog.c:573
AlterTableType subtype
Definition: parsenodes.h:1530
#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:519
Oid MyDatabaseTableSpace
Definition: globals.c:75
void EventTriggerAlterTableStart(Node *parsetree)
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:41
#define ACL_CREATE
Definition: parsenodes.h:73
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:2960
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3351
HeapScanDesc heap_beginscan_catalog(Relation relation, int nkeys, ScanKey key)
Definition: heapam.c:1349
#define ereport(elevel, rest)
Definition: elog.h:132
List * lappend(List *list, void *datum)
Definition: list.c:128
AclResult
Definition: acl.h:169
HeapTuple heap_getnext(HeapScanDesc scan, ScanDirection direction)
Definition: heapam.c:1559
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1234
bool IsSystemNamespace(Oid namespaceId)
Definition: catalog.c:161
#define InvalidOid
Definition: postgres_ext.h:36
#define NOTICE
Definition: elog.h:35
#define makeNode(_type_)
Definition: nodes.h:512
List * roleSpecsToIds(List *memberNames)
Definition: user.c:1341
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:505
#define NULL
Definition: c.h:215
bool pg_class_ownercheck(Oid class_oid, Oid roleid)
Definition: aclchk.c:4489
FormData_pg_class * Form_pg_class
Definition: pg_class.h:91
void AlterTableInternal(Oid relid, List *cmds, bool recurse)
Definition: tablecmds.c:2788
#define AccessExclusiveLock
Definition: lockdefs.h:46
int errmsg(const char *fmt,...)
Definition: elog.c:795
char * get_tablespace_name(Oid spc_oid)
Definition: tablespace.c:1416
#define NameStr(name)
Definition: c.h:483
#define RELKIND_INDEX
Definition: pg_class.h:154
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
bool isAnyTempNamespace(Oid namespaceId)
Definition: namespace.c:3016
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:670
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:105
#define RELKIND_RELATION
Definition: pg_class.h:153
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 11266 of file tablecmds.c.

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

Referenced by ExecAlterObjectSchemaStmt().

11267 {
11268  Relation rel;
11269  Oid relid;
11270  Oid oldNspOid;
11271  Oid nspOid;
11272  RangeVar *newrv;
11273  ObjectAddresses *objsMoved;
11274  ObjectAddress myself;
11275 
11277  stmt->missing_ok, false,
11279  (void *) stmt);
11280 
11281  if (!OidIsValid(relid))
11282  {
11283  ereport(NOTICE,
11284  (errmsg("relation \"%s\" does not exist, skipping",
11285  stmt->relation->relname)));
11286  return InvalidObjectAddress;
11287  }
11288 
11289  rel = relation_open(relid, NoLock);
11290 
11291  oldNspOid = RelationGetNamespace(rel);
11292 
11293  /* If it's an owned sequence, disallow moving it by itself. */
11294  if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
11295  {
11296  Oid tableId;
11297  int32 colId;
11298 
11299  if (sequenceIsOwned(relid, &tableId, &colId))
11300  ereport(ERROR,
11301  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
11302  errmsg("cannot move an owned sequence into another schema"),
11303  errdetail("Sequence \"%s\" is linked to table \"%s\".",
11305  get_rel_name(tableId))));
11306  }
11307 
11308  /* Get and lock schema OID and check its permissions. */
11309  newrv = makeRangeVar(stmt->newschema, RelationGetRelationName(rel), -1);
11311 
11312  /* common checks on switching namespaces */
11313  CheckSetNamespace(oldNspOid, nspOid, RelationRelationId, relid);
11314 
11315  objsMoved = new_object_addresses();
11316  AlterTableNamespaceInternal(rel, oldNspOid, nspOid, objsMoved);
11317  free_object_addresses(objsMoved);
11318 
11319  ObjectAddressSet(myself, RelationRelationId, relid);
11320 
11321  if (oldschema)
11322  *oldschema = oldNspOid;
11323 
11324  /* close rel, but keep lock until commit */
11325  relation_close(rel, NoLock);
11326 
11327  return myself;
11328 }
bool sequenceIsOwned(Oid seqId, Oid *tableId, int32 *colId)
Definition: pg_depend.c:503
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, bool missing_ok, bool nowait, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:232
#define RelationRelationId
Definition: pg_class.h:29
int errcode(int sqlerrcode)
Definition: elog.c:573
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1210
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2022
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2293
Form_pg_class rd_rel
Definition: rel.h:100
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:519
signed int int32
Definition: c.h:242
char * relname
Definition: primnodes.h:74
#define ERROR
Definition: elog.h:41
void CheckSetNamespace(Oid oldNspOid, Oid nspOid, Oid classid, Oid objid)
Definition: namespace.c:2777
void AlterTableNamespaceInternal(Relation rel, Oid oldNspOid, Oid nspOid, ObjectAddresses *objsMoved)
Definition: tablecmds.c:11336
#define NoLock
Definition: lockdefs.h:34
static void RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg)
Definition: tablecmds.c:11845
int errdetail(const char *fmt,...)
Definition: elog.c:868
#define RelationGetRelationName(relation)
Definition: rel.h:365
#define ereport(elevel, rest)
Definition: elog.h:132
Oid RangeVarGetAndCheckCreationNamespace(RangeVar *relation, LOCKMODE lockmode, Oid *existing_relation_id)
Definition: namespace.c:522
#define NOTICE
Definition: elog.h:35
#define NULL
Definition: c.h:215
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define AccessExclusiveLock
Definition: lockdefs.h:46
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:795
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1052
#define RELKIND_SEQUENCE
Definition: pg_class.h:155
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1670
RangeVar * makeRangeVar(char *schemaname, char *relname, int location)
Definition: makefuncs.c:410
#define RelationGetNamespace(relation)
Definition: rel.h:372
void AlterTableNamespaceInternal ( Relation  rel,
Oid  oldNspOid,
Oid  nspOid,
ObjectAddresses objsMoved 
)

Definition at line 11336 of file tablecmds.c.

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

Referenced by AlterObjectNamespace_oid(), and AlterTableNamespace().

11338 {
11339  Relation classRel;
11340 
11341  Assert(objsMoved != NULL);
11342 
11343  /* OK, modify the pg_class row and pg_depend entry */
11345 
11346  AlterRelationNamespaceInternal(classRel, RelationGetRelid(rel), oldNspOid,
11347  nspOid, true, objsMoved);
11348 
11349  /* Fix the table's row type too */
11350  AlterTypeNamespaceInternal(rel->rd_rel->reltype,
11351  nspOid, false, false, objsMoved);
11352 
11353  /* Fix other dependent stuff */
11354  if (rel->rd_rel->relkind == RELKIND_RELATION ||
11355  rel->rd_rel->relkind == RELKIND_MATVIEW)
11356  {
11357  AlterIndexNamespaces(classRel, rel, oldNspOid, nspOid, objsMoved);
11358  AlterSeqNamespaces(classRel, rel, oldNspOid, nspOid,
11359  objsMoved, AccessExclusiveLock);
11360  AlterConstraintNamespaces(RelationGetRelid(rel), oldNspOid, nspOid,
11361  false, objsMoved);
11362  }
11363 
11364  heap_close(classRel, RowExclusiveLock);
11365 }
#define RelationRelationId
Definition: pg_class.h:29
#define RELKIND_MATVIEW
Definition: pg_class.h:160
Oid AlterTypeNamespaceInternal(Oid typeOid, Oid nspOid, bool isImplicitArray, bool errorOnTableType, ObjectAddresses *objsMoved)
Definition: typecmds.c:3490
#define heap_close(r, l)
Definition: heapam.h:97
Form_pg_class rd_rel
Definition: rel.h:100
static void AlterIndexNamespaces(Relation classRel, Relation rel, Oid oldNspOid, Oid newNspOid, ObjectAddresses *objsMoved)
Definition: tablecmds.c:11438
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:11483
#define RowExclusiveLock
Definition: lockdefs.h:38
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1234
#define NULL
Definition: c.h:215
#define Assert(condition)
Definition: c.h:656
void AlterRelationNamespaceInternal(Relation classRel, Oid relOid, Oid oldNspOid, Oid newNspOid, bool hasDependEntry, ObjectAddresses *objsMoved)
Definition: tablecmds.c:11373
#define AccessExclusiveLock
Definition: lockdefs.h:46
#define RELKIND_RELATION
Definition: pg_class.h:153
#define RelationGetRelid(relation)
Definition: rel.h:345
void AtEOSubXact_on_commit_actions ( bool  isCommit,
SubTransactionId  mySubid,
SubTransactionId  parentSubid 
)

Definition at line 11735 of file tablecmds.c.

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

Referenced by AbortSubTransaction(), and CommitSubTransaction().

11737 {
11738  ListCell *cur_item;
11739  ListCell *prev_item;
11740 
11741  prev_item = NULL;
11742  cur_item = list_head(on_commits);
11743 
11744  while (cur_item != NULL)
11745  {
11746  OnCommitItem *oc = (OnCommitItem *) lfirst(cur_item);
11747 
11748  if (!isCommit && oc->creating_subid == mySubid)
11749  {
11750  /* cur_item must be removed */
11751  on_commits = list_delete_cell(on_commits, cur_item, prev_item);
11752  pfree(oc);
11753  if (prev_item)
11754  cur_item = lnext(prev_item);
11755  else
11756  cur_item = list_head(on_commits);
11757  }
11758  else
11759  {
11760  /* cur_item must be preserved */
11761  if (oc->creating_subid == mySubid)
11762  oc->creating_subid = parentSubid;
11763  if (oc->deleting_subid == mySubid)
11764  oc->deleting_subid = isCommit ? parentSubid : InvalidSubTransactionId;
11765  prev_item = cur_item;
11766  cur_item = lnext(prev_item);
11767  }
11768  }
11769 }
SubTransactionId creating_subid
Definition: tablecmds.c:112
void pfree(void *pointer)
Definition: mcxt.c:993
static List * on_commits
Definition: tablecmds.c:116
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:113
#define NULL
Definition: c.h:215
#define lfirst(lc)
Definition: pg_list.h:106
#define InvalidSubTransactionId
Definition: c.h:388
void AtEOXact_on_commit_actions ( bool  isCommit)

Definition at line 11693 of file tablecmds.c.

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

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

11694 {
11695  ListCell *cur_item;
11696  ListCell *prev_item;
11697 
11698  prev_item = NULL;
11699  cur_item = list_head(on_commits);
11700 
11701  while (cur_item != NULL)
11702  {
11703  OnCommitItem *oc = (OnCommitItem *) lfirst(cur_item);
11704 
11705  if (isCommit ? oc->deleting_subid != InvalidSubTransactionId :
11707  {
11708  /* cur_item must be removed */
11709  on_commits = list_delete_cell(on_commits, cur_item, prev_item);
11710  pfree(oc);
11711  if (prev_item)
11712  cur_item = lnext(prev_item);
11713  else
11714  cur_item = list_head(on_commits);
11715  }
11716  else
11717  {
11718  /* cur_item must be preserved */
11721  prev_item = cur_item;
11722  cur_item = lnext(prev_item);
11723  }
11724  }
11725 }
SubTransactionId creating_subid
Definition: tablecmds.c:112
void pfree(void *pointer)
Definition: mcxt.c:993
static List * on_commits
Definition: tablecmds.c:116
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:113
#define NULL
Definition: c.h:215
#define lfirst(lc)
Definition: pg_list.h:106
#define InvalidSubTransactionId
Definition: c.h:388
void ATExecChangeOwner ( Oid  relationOid,
Oid  newOwnerId,
bool  recursing,
LOCKMODE  lockmode 
)

Definition at line 8870 of file tablecmds.c.

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

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

8871 {
8872  Relation target_rel;
8873  Relation class_rel;
8874  HeapTuple tuple;
8875  Form_pg_class tuple_class;
8876 
8877  /*
8878  * Get exclusive lock till end of transaction on the target table. Use
8879  * relation_open so that we can work on indexes and sequences.
8880  */
8881  target_rel = relation_open(relationOid, lockmode);
8882 
8883  /* Get its pg_class tuple, too */
8885 
8886  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relationOid));
8887  if (!HeapTupleIsValid(tuple))
8888  elog(ERROR, "cache lookup failed for relation %u", relationOid);
8889  tuple_class = (Form_pg_class) GETSTRUCT(tuple);
8890 
8891  /* Can we change the ownership of this tuple? */
8892  switch (tuple_class->relkind)
8893  {
8894  case RELKIND_RELATION:
8895  case RELKIND_VIEW:
8896  case RELKIND_MATVIEW:
8897  case RELKIND_FOREIGN_TABLE:
8898  /* ok to change owner */
8899  break;
8900  case RELKIND_INDEX:
8901  if (!recursing)
8902  {
8903  /*
8904  * Because ALTER INDEX OWNER used to be allowed, and in fact
8905  * is generated by old versions of pg_dump, we give a warning
8906  * and do nothing rather than erroring out. Also, to avoid
8907  * unnecessary chatter while restoring those old dumps, say
8908  * nothing at all if the command would be a no-op anyway.
8909  */
8910  if (tuple_class->relowner != newOwnerId)
8911  ereport(WARNING,
8912  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
8913  errmsg("cannot change owner of index \"%s\"",
8914  NameStr(tuple_class->relname)),
8915  errhint("Change the ownership of the index's table, instead.")));
8916  /* quick hack to exit via the no-op path */
8917  newOwnerId = tuple_class->relowner;
8918  }
8919  break;
8920  case RELKIND_SEQUENCE:
8921  if (!recursing &&
8922  tuple_class->relowner != newOwnerId)
8923  {
8924  /* if it's an owned sequence, disallow changing it by itself */
8925  Oid tableId;
8926  int32 colId;
8927 
8928  if (sequenceIsOwned(relationOid, &tableId, &colId))
8929  ereport(ERROR,
8930  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
8931  errmsg("cannot change owner of sequence \"%s\"",
8932  NameStr(tuple_class->relname)),
8933  errdetail("Sequence \"%s\" is linked to table \"%s\".",
8934  NameStr(tuple_class->relname),
8935  get_rel_name(tableId))));
8936  }
8937  break;
8939  if (recursing)
8940  break;
8941  ereport(ERROR,
8942  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
8943  errmsg("\"%s\" is a composite type",
8944  NameStr(tuple_class->relname)),
8945  errhint("Use ALTER TYPE instead.")));
8946  break;
8947  case RELKIND_TOASTVALUE:
8948  if (recursing)
8949  break;
8950  /* FALL THRU */
8951  default:
8952  ereport(ERROR,
8953  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
8954  errmsg("\"%s\" is not a table, view, sequence, or foreign table",
8955  NameStr(tuple_class->relname))));
8956  }
8957 
8958  /*
8959  * If the new owner is the same as the existing owner, consider the
8960  * command to have succeeded. This is for dump restoration purposes.
8961  */
8962  if (tuple_class->relowner != newOwnerId)
8963  {
8964  Datum repl_val[Natts_pg_class];
8965  bool repl_null[Natts_pg_class];
8966  bool repl_repl[Natts_pg_class];
8967  Acl *newAcl;
8968  Datum aclDatum;
8969  bool isNull;
8970  HeapTuple newtuple;
8971 
8972  /* skip permission checks when recursing to index or toast table */
8973  if (!recursing)
8974  {
8975  /* Superusers can always do it */
8976  if (!superuser())
8977  {
8978  Oid namespaceOid = tuple_class->relnamespace;
8979  AclResult aclresult;
8980 
8981  /* Otherwise, must be owner of the existing object */
8982  if (!pg_class_ownercheck(relationOid, GetUserId()))
8984  RelationGetRelationName(target_rel));
8985 
8986  /* Must be able to become new owner */
8987  check_is_member_of_role(GetUserId(), newOwnerId);
8988 
8989  /* New owner must have CREATE privilege on namespace */
8990  aclresult = pg_namespace_aclcheck(namespaceOid, newOwnerId,
8991  ACL_CREATE);
8992  if (aclresult != ACLCHECK_OK)
8994  get_namespace_name(namespaceOid));
8995  }
8996  }
8997 
8998  memset(repl_null, false, sizeof(repl_null));
8999  memset(repl_repl, false, sizeof(repl_repl));
9000 
9001  repl_repl[Anum_pg_class_relowner - 1] = true;
9002  repl_val[Anum_pg_class_relowner - 1] = ObjectIdGetDatum(newOwnerId);
9003 
9004  /*
9005  * Determine the modified ACL for the new owner. This is only
9006  * necessary when the ACL is non-null.
9007  */
9008  aclDatum = SysCacheGetAttr(RELOID, tuple,
9010  &isNull);
9011  if (!isNull)
9012  {
9013  newAcl = aclnewowner(DatumGetAclP(aclDatum),
9014  tuple_class->relowner, newOwnerId);
9015  repl_repl[Anum_pg_class_relacl - 1] = true;
9016  repl_val[Anum_pg_class_relacl - 1] = PointerGetDatum(newAcl);
9017  }
9018 
9019  newtuple = heap_modify_tuple(tuple, RelationGetDescr(class_rel), repl_val, repl_null, repl_repl);
9020 
9021  simple_heap_update(class_rel, &newtuple->t_self, newtuple);
9022  CatalogUpdateIndexes(class_rel, newtuple);
9023 
9024  heap_freetuple(newtuple);
9025 
9026  /*
9027  * We must similarly update any per-column ACLs to reflect the new
9028  * owner; for neatness reasons that's split out as a subroutine.
9029  */
9030  change_owner_fix_column_acls(relationOid,
9031  tuple_class->relowner,
9032  newOwnerId);
9033 
9034  /*
9035  * Update owner dependency reference, if any. A composite type has
9036  * none, because it's tracked for the pg_type entry instead of here;
9037  * indexes and TOAST tables don't have their own entries either.
9038  */
9039  if (tuple_class->relkind != RELKIND_COMPOSITE_TYPE &&
9040  tuple_class->relkind != RELKIND_INDEX &&
9041  tuple_class->relkind != RELKIND_TOASTVALUE)
9043  newOwnerId);
9044 
9045  /*
9046  * Also change the ownership of the table's row type, if it has one
9047  */
9048  if (tuple_class->relkind != RELKIND_INDEX)
9049  AlterTypeOwnerInternal(tuple_class->reltype, newOwnerId,
9050  tuple_class->relkind == RELKIND_COMPOSITE_TYPE);
9051 
9052  /*
9053  * If we are operating on a table or materialized view, also change
9054  * the ownership of any indexes and sequences that belong to the
9055  * relation, as well as its toast table (if it has one).
9056  */
9057  if (tuple_class->relkind == RELKIND_RELATION ||
9058  tuple_class->relkind == RELKIND_MATVIEW ||
9059  tuple_class->relkind == RELKIND_TOASTVALUE)
9060  {
9061  List *index_oid_list;
9062  ListCell *i;
9063 
9064  /* Find all the indexes belonging to this relation */
9065  index_oid_list = RelationGetIndexList(target_rel);
9066 
9067  /* For each index, recursively change its ownership */
9068  foreach(i, index_oid_list)
9069  ATExecChangeOwner(lfirst_oid(i), newOwnerId, true, lockmode);
9070 
9071  list_free(index_oid_list);
9072  }
9073 
9074  if (tuple_class->relkind == RELKIND_RELATION ||
9075  tuple_class->relkind == RELKIND_MATVIEW)
9076  {
9077  /* If it has a toast table, recurse to change its ownership */
9078  if (tuple_class->reltoastrelid != InvalidOid)
9079  ATExecChangeOwner(tuple_class->reltoastrelid, newOwnerId,
9080  true, lockmode);
9081 
9082  /* If it has dependent sequences, recurse to change them too */
9083  change_owner_recurse_to_sequences(relationOid, newOwnerId, lockmode);
9084  }
9085  }
9086 
9088 
9089  ReleaseSysCache(tuple);
9090  heap_close(class_rel, RowExclusiveLock);
9091  relation_close(target_rel, NoLock);
9092 }
#define Natts_pg_class
Definition: pg_class.h:98
bool sequenceIsOwned(Oid seqId, Oid *tableId, int32 *colId)
Definition: pg_depend.c:503
int errhint(const char *fmt,...)
Definition: elog.c:982
#define GETSTRUCT(TUP)
Definition: htup_details.h:631
#define Anum_pg_class_relacl
Definition: pg_class.h:127
#define RelationGetDescr(relation)
Definition: rel.h:357
Oid GetUserId(void)
Definition: miscinit.c:274
#define DatumGetAclP(X)
Definition: acl.h:112
#define PointerGetDatum(X)
Definition: postgres.h:564
#define RelationRelationId
Definition: pg_class.h:29
#define RELKIND_MATVIEW
Definition: pg_class.h:160
int errcode(int sqlerrcode)
Definition: elog.c:573
bool superuser(void)
Definition: superuser.c:47
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1210
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1306
unsigned int Oid
Definition: postgres_ext.h:31
AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4427
#define RELKIND_COMPOSITE_TYPE
Definition: pg_class.h:158
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:141
signed int int32
Definition: c.h:242
void AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId, bool hasDependEntry)
Definition: typecmds.c:3351
void changeDependencyOnOwner(Oid classId, Oid objectId, Oid newOwnerId)
Definition: pg_shdepend.c:304
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:41
#define ACL_CREATE
Definition: parsenodes.h:73
ItemPointerData t_self
Definition: htup.h:65
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:2960
#define NoLock
Definition: lockdefs.h:34
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3351
#define RowExclusiveLock
Definition: lockdefs.h:38
int errdetail(const char *fmt,...)
Definition: elog.c:868
#define RelationGetRelationName(relation)
Definition: rel.h:365
#define RELKIND_FOREIGN_TABLE
Definition: pg_class.h:159
void check_is_member_of_role(Oid member, Oid role)
Definition: acl.c:4875
#define ereport(elevel, rest)
Definition: elog.h:132
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
void ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing, LOCKMODE lockmode)
Definition: tablecmds.c:8870
#define WARNING
Definition: elog.h:38
#define RELKIND_TOASTVALUE
Definition: pg_class.h:156
AclResult
Definition: acl.h:169
uintptr_t Datum
Definition: postgres.h:374
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:989
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1151
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1234
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
void CatalogUpdateIndexes(Relation heapRel, HeapTuple heapTuple)
Definition: indexing.c:157
bool pg_class_ownercheck(Oid class_oid, Oid roleid)
Definition: aclchk.c:4489
static void change_owner_recurse_to_sequences(Oid relationOid, Oid newOwnerId, LOCKMODE lockmode)
Definition: tablecmds.c:9167
void simple_heap_update(Relation relation, ItemPointer otid, HeapTuple tup)
Definition: heapam.c:4148
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:3808
FormData_pg_class * Form_pg_class
Definition: pg_class.h:91
static void change_owner_fix_column_acls(Oid relationOid, Oid oldOwnerId, Oid newOwnerId)
Definition: tablecmds.c:9101
int errmsg(const char *fmt,...)
Definition: elog.c:795
#define RELKIND_VIEW
Definition: pg_class.h:157
void list_free(List *list)
Definition: list.c:1133
int i
#define NameStr(name)
Definition: c.h:483
#define RELKIND_INDEX
Definition: pg_class.h:154
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1052
#define elog
Definition: elog.h:228
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:791
#define RELKIND_RELATION
Definition: pg_class.h:153
#define RELKIND_SEQUENCE
Definition: pg_class.h:155
Definition: pg_list.h:45
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1670
Acl * aclnewowner(const Acl *old_acl, Oid oldOwnerId, Oid newOwnerId)
Definition: acl.c:1034
#define lfirst_oid(lc)
Definition: pg_list.h:108
#define Anum_pg_class_relowner
Definition: pg_class.h:103
void check_of_type ( HeapTuple  typetuple)

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

4613 {
4614  Form_pg_type typ = (Form_pg_type) GETSTRUCT(typetuple);
4615  bool typeOk = false;
4616 
4617  if (typ->typtype == TYPTYPE_COMPOSITE)
4618  {
4619  Relation typeRelation;
4620 
4621  Assert(OidIsValid(typ->typrelid));
4622  typeRelation = relation_open(typ->typrelid, AccessShareLock);
4623  typeOk = (typeRelation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE);
4624 
4625  /*
4626  * Close the parent rel, but keep our AccessShareLock on it until xact
4627  * commit. That will prevent someone else from deleting or ALTERing
4628  * the type before the typed table creation/conversion commits.
4629  */
4630  relation_close(typeRelation, NoLock);
4631  }
4632  if (!typeOk)
4633  ereport(ERROR,
4634  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
4635  errmsg("type %s is not a composite type",
4636  format_type_be(HeapTupleGetOid(typetuple)))));
4637 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:631
#define TYPTYPE_COMPOSITE
Definition: pg_type.h:707
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:573
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1210
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:100
#define OidIsValid(objectId)
Definition: c.h:519
#define RELKIND_COMPOSITE_TYPE
Definition: pg_class.h:158
#define ERROR
Definition: elog.h:41
#define NoLock
Definition: lockdefs.h:34
#define ereport(elevel, rest)
Definition: elog.h:132
#define Assert(condition)
Definition: c.h:656
int errmsg(const char *fmt,...)
Definition: elog.c:795
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1052
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:670
void CheckTableNotInUse ( Relation  rel,
const char *  stmt 
)

Definition at line 2683 of file tablecmds.c.

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

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

2684 {
2685  int expected_refcnt;
2686 
2687  expected_refcnt = rel->rd_isnailed ? 2 : 1;
2688  if (rel->rd_refcnt != expected_refcnt)
2689  ereport(ERROR,
2690  (errcode(ERRCODE_OBJECT_IN_USE),
2691  /* translator: first %s is a SQL command, eg ALTER TABLE */
2692  errmsg("cannot %s \"%s\" because "
2693  "it is being used by active queries in this session",
2694  stmt, RelationGetRelationName(rel))));
2695 
2696  if (rel->rd_rel->relkind != RELKIND_INDEX &&
2698  ereport(ERROR,
2699  (errcode(ERRCODE_OBJECT_IN_USE),
2700  /* translator: first %s is a SQL command, eg ALTER TABLE */
2701  errmsg("cannot %s \"%s\" because "
2702  "it has pending trigger events",
2703  stmt, RelationGetRelationName(rel))));
2704 }
bool rd_isnailed
Definition: rel.h:78
int errcode(int sqlerrcode)
Definition: elog.c:573
Form_pg_class rd_rel
Definition: rel.h:100
#define ERROR
Definition: elog.h:41
#define RelationGetRelationName(relation)
Definition: rel.h:365
#define ereport(elevel, rest)
Definition: elog.h:132
bool AfterTriggerPendingOnRel(Oid relid)
Definition: trigger.c:4754
int errmsg(const char *fmt,...)
Definition: elog.c:795
int rd_refcnt
Definition: rel.h:75
#define RELKIND_INDEX
Definition: pg_class.h:154
#define RelationGetRelid(relation)
Definition: rel.h:345
ObjectAddress DefineRelation ( CreateStmt stmt,
char  relkind,
Oid  ownerId,
ObjectAddress typaddress 
)

Definition at line 452 of file tablecmds.c.

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

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

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

Definition at line 998 of file tablecmds.c.

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

Referenced by standard_ProcessUtility().

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

Definition at line 4458 of file tablecmds.c.

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

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

4460 {
4461  Relation depRel;
4462  ScanKeyData key[2];
4463  SysScanDesc depScan;
4464  HeapTuple depTup;
4465  Oid arrayOid;
4466 
4467  /*
4468  * We scan pg_depend to find those things that depend on the rowtype. (We
4469  * assume we can ignore refobjsubid for a rowtype.)
4470  */
4472 
4473  ScanKeyInit(&key[0],
4475  BTEqualStrategyNumber, F_OIDEQ,
4477  ScanKeyInit(&key[1],
4479  BTEqualStrategyNumber, F_OIDEQ,
4480  ObjectIdGetDatum(typeOid));
4481 
4482  depScan = systable_beginscan(depRel, DependReferenceIndexId, true,
4483  NULL, 2, key);
4484 
4485  while (HeapTupleIsValid(depTup = systable_getnext(depScan)))
4486  {
4487  Form_pg_depend pg_depend = (Form_pg_depend) GETSTRUCT(depTup);
4488  Relation rel;
4489  Form_pg_attribute att;
4490 
4491  /* Ignore dependees that aren't user columns of relations */
4492  /* (we assume system columns are never of rowtypes) */
4493  if (pg_depend->classid != RelationRelationId ||
4494  pg_depend->objsubid <= 0)
4495  continue;
4496 
4497  rel = relation_open(pg_depend->objid, AccessShareLock);
4498  att = rel->rd_att->attrs[pg_depend->objsubid - 1];
4499 
4500  if (rel->rd_rel->relkind == RELKIND_RELATION ||
4501  rel->rd_rel->relkind == RELKIND_MATVIEW)
4502  {
4503  if (origTypeName)
4504  ereport(ERROR,
4505  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4506  errmsg("cannot alter type \"%s\" because column \"%s.%s\" uses it",
4507  origTypeName,
4509  NameStr(att->attname))));
4510  else if (origRelation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
4511  ereport(ERROR,
4512  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4513  errmsg("cannot alter type \"%s\" because column \"%s.%s\" uses it",
4514  RelationGetRelationName(origRelation),
4516  NameStr(att->attname))));
4517  else if (origRelation->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
4518  ereport(ERROR,
4519  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4520  errmsg("cannot alter foreign table \"%s\" because column \"%s.%s\" uses its row type",
4521  RelationGetRelationName(origRelation),
4523  NameStr(att->attname))));
4524  else
4525  ereport(ERROR,
4526  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4527  errmsg("cannot alter table \"%s\" because column \"%s.%s\" uses its row type",
4528  RelationGetRelationName(origRelation),
4530  NameStr(att->attname))));
4531  }
4532  else if (OidIsValid(rel->rd_rel->reltype))
4533  {
4534  /*
4535  * A view or composite type itself isn't a problem, but we must
4536  * recursively check for indirect dependencies via its rowtype.
4537  */
4539  origRelation, origTypeName);
4540  }
4541 
4543  }
4544 
4545  systable_endscan(depScan);
4546 
4548 
4549  /*
4550  * If there's an array type for the rowtype, must check for uses of it,
4551  * too.
4552  */
4553  arrayOid = get_array_type(typeOid);
4554  if (OidIsValid(arrayOid))
4555  find_composite_type_dependencies(arrayOid, origRelation, origTypeName);
4556 }
#define Anum_pg_depend_refobjid
Definition: pg_depend.h:72
#define Anum_pg_depend_refclassid
Definition: pg_depend.h:71
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:493
#define GETSTRUCT(TUP)
Definition: htup_details.h:631
Oid get_array_type(Oid typid)
Definition: lsyscache.c:2434
#define RelationRelationId
Definition: pg_class.h:29
#define DependReferenceIndexId
Definition: indexing.h:141
void find_composite_type_dependencies(Oid typeOid, Relation origRelation, const char *origTypeName)
Definition: tablecmds.c:4458
#define DependRelationId
Definition: pg_depend.h:29
Form_pg_attribute * attrs
Definition: tupdesc.h:74
#define RELKIND_MATVIEW
Definition: pg_class.h:160
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:573
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1210
Form_pg_class rd_rel
Definition: rel.h:100
unsigned int Oid
Definition: postgres_ext.h:31
#define TypeRelationId
Definition: pg_type.h:34
#define OidIsValid(objectId)
Definition: c.h:519
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:322
#define RELKIND_COMPOSITE_TYPE
Definition: pg_class.h:158
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:410
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:41
#define RelationGetRelationName(relation)
Definition: rel.h:365
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:184
#define RELKIND_FOREIGN_TABLE
Definition: pg_class.h:159
FormData_pg_depend * Form_pg_depend
Definition: pg_depend.h:61
#define ereport(elevel, rest)
Definition: elog.h:132
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1234
TupleDesc rd_att
Definition: rel.h:101
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:215
int errmsg(const char *fmt,...)
Definition: elog.c:795
#define NameStr(name)
Definition: c.h:483
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:1052
#define RELKIND_RELATION
Definition: pg_class.h:153
#define BTEqualStrategyNumber
Definition: stratnum.h:31
void PreCommit_on_commit_actions ( void  )

Definition at line 11622 of file tablecmds.c.

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

Referenced by CommitTransaction(), and PrepareTransaction().

11623 {
11624  ListCell *l;
11625  List *oids_to_truncate = NIL;
11626 
11627  foreach(l, on_commits)
11628  {
11629  OnCommitItem *oc = (OnCommitItem *) lfirst(l);
11630 
11631  /* Ignore entry if already dropped in this xact */
11633  continue;
11634 
11635  switch (oc->oncommit)
11636  {
11637  case ONCOMMIT_NOOP:
11639  /* Do nothing (there shouldn't be such entries, actually) */
11640  break;
11641  case ONCOMMIT_DELETE_ROWS:
11642 
11643  /*
11644  * If this transaction hasn't accessed any temporary
11645  * relations, we can skip truncating ON COMMIT DELETE ROWS
11646  * tables, as they must still be empty.
11647  */
11649  oids_to_truncate = lappend_oid(oids_to_truncate, oc->relid);
11650  break;
11651  case ONCOMMIT_DROP:
11652  {
11653  ObjectAddress object;
11654 
11655  object.classId = RelationRelationId;
11656  object.objectId = oc->relid;
11657  object.objectSubId = 0;
11658 
11659  /*
11660  * Since this is an automatic drop, rather than one
11661  * directly initiated by the user, we pass the
11662  * PERFORM_DELETION_INTERNAL flag.
11663  */
11664  performDeletion(&object,
11666 
11667  /*
11668  * Note that table deletion will call
11669  * remove_on_commit_action, so the entry should get marked
11670  * as deleted.
11671  */
11673  break;
11674  }
11675  }
11676  }
11677  if (oids_to_truncate != NIL)
11678  {
11679  heap_truncate(oids_to_truncate);
11680  CommandCounterIncrement(); /* XXX needed? */
11681  }
11682 }
#define NIL
Definition: pg_list.h:69
OnCommitAction oncommit
Definition: tablecmds.c:103
#define RelationRelationId
Definition: pg_class.h:29
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
static List * on_commits
Definition: tablecmds.c:116
void performDeletion(const ObjectAddress *object, DropBehavior behavior, int flags)
Definition: dependency.c:265
bool MyXactAccessedTempRel
Definition: xact.c:114
SubTransactionId deleting_subid
Definition: tablecmds.c:113
void CommandCounterIncrement(void)
Definition: xact.c:919
#define Assert(condition)
Definition: c.h:656
#define lfirst(lc)
Definition: pg_list.h:106
void heap_truncate(List *relids)
Definition: heap.c:2745
#define InvalidSubTransactionId
Definition: c.h:388
Definition: pg_list.h:45
#define PERFORM_DELETION_INTERNAL
Definition: dependency.h:164
void RangeVarCallbackOwnsRelation ( const RangeVar relation,
Oid  relId,
Oid  oldRelId,
void *  noCatalogs 
)

Definition at line 11813 of file tablecmds.c.

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

Referenced by ProcessUtilitySlow().

11815 {
11816  HeapTuple tuple;
11817 
11818  /* Nothing to do if the relation was not found. */
11819  if (!OidIsValid(relId))
11820  return;
11821 
11822  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relId));
11823  if (!HeapTupleIsValid(tuple)) /* should not happen */
11824  elog(ERROR, "cache lookup failed for relation %u", relId);
11825 
11826  if (!pg_class_ownercheck(relId, GetUserId()))
11828  relation->relname);
11829 
11830  if (!allowSystemTableMods &&
11831  IsSystemClass(relId, (Form_pg_class) GETSTRUCT(tuple)))
11832  ereport(ERROR,
11833  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
11834  errmsg("permission denied: \"%s\" is a system catalog",
11835  relation->relname)));
11836 
11837  ReleaseSysCache(tuple);
11838 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:631
Oid GetUserId(void)
Definition: miscinit.c:274
int errcode(int sqlerrcode)
Definition: elog.c:573
#define OidIsValid(objectId)
Definition: c.h:519
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:141
bool IsSystemClass(Oid relid, Form_pg_class reltuple)
Definition: catalog.c:73
char * relname
Definition: primnodes.h:74
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:41
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3351
#define ereport(elevel, rest)
Definition: elog.h:132
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:989
bool allowSystemTableMods
Definition: globals.c:108
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
bool pg_class_ownercheck(Oid class_oid, Oid roleid)
Definition: aclchk.c:4489
FormData_pg_class * Form_pg_class
Definition: pg_class.h:91
int errmsg(const char *fmt,...)
Definition: elog.c:795
#define elog
Definition: elog.h:228
void RangeVarCallbackOwnsTable ( const RangeVar relation,
Oid  relId,
Oid  oldRelId,
void *  arg 
)

Definition at line 11780 of file tablecmds.c.

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

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

11782 {
11783  char relkind;
11784 
11785  /* Nothing to do if the relation was not found. */
11786  if (!OidIsValid(relId))
11787  return;
11788 
11789  /*
11790  * If the relation does exist, check whether it's an index. But note that
11791  * the relation might have been dropped between the time we did the name
11792  * lookup and now. In that case, there's nothing to do.
11793  */
11794  relkind = get_rel_relkind(relId);
11795  if (!relkind)
11796  return;
11797  if (relkind != RELKIND_RELATION && relkind != RELKIND_TOASTVALUE &&
11798  relkind != RELKIND_MATVIEW)
11799  ereport(ERROR,
11800  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
11801  errmsg("\"%s\" is not a table or materialized view", relation->relname)));
11802 
11803  /* Check permissions */
11804  if (!pg_class_ownercheck(relId, GetUserId()))
11806 }
Oid GetUserId(void)
Definition: miscinit.c:274
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:1745
#define RELKIND_MATVIEW
Definition: pg_class.h:160
int errcode(int sqlerrcode)
Definition: elog.c:573
#define OidIsValid(objectId)
Definition: c.h:519
char * relname
Definition: primnodes.h:74
#define ERROR
Definition: elog.h:41
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3351
#define ereport(elevel, rest)
Definition: elog.h:132
#define RELKIND_TOASTVALUE
Definition: pg_class.h:156
bool pg_class_ownercheck(Oid class_oid, Oid roleid)
Definition: aclchk.c:4489
int errmsg(const char *fmt,...)
Definition: elog.c:795
#define RELKIND_RELATION
Definition: pg_class.h:153
void register_on_commit_action ( Oid  relid,
OnCommitAction  action 
)

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

11569 {
11570  OnCommitItem *oc;
11571  MemoryContext oldcxt;
11572 
11573  /*
11574  * We needn't bother registering the relation unless there is an ON COMMIT
11575  * action we need to take.
11576  */
11577  if (action == ONCOMMIT_NOOP || action == ONCOMMIT_PRESERVE_ROWS)
11578  return;
11579 
11581 
11582  oc = (OnCommitItem *) palloc(sizeof(OnCommitItem));
11583  oc->relid = relid;
11584  oc->oncommit = action;
11587 
11588  on_commits = lcons(oc, on_commits);
11589 
11590  MemoryContextSwitchTo(oldcxt);
11591 }
OnCommitAction oncommit
Definition: tablecmds.c:103
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
SubTransactionId creating_subid
Definition: tablecmds.c:112
static List * on_commits
Definition: tablecmds.c:116
SubTransactionId deleting_subid
Definition: tablecmds.c:113
List * lcons(void *datum, List *list)
Definition: list.c:259
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:646
#define InvalidSubTransactionId
Definition: c.h:388
void * palloc(Size size)
Definition: mcxt.c:892
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
void remove_on_commit_action ( Oid  relid)

Definition at line 11599 of file tablecmds.c.

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

Referenced by heap_drop_with_catalog().

11600 {
11601  ListCell *l;
11602 
11603  foreach(l, on_commits)
11604  {
11605  OnCommitItem *oc = (OnCommitItem *) lfirst(l);
11606 
11607  if (oc->relid == relid)
11608  {
11610  break;
11611  }
11612  }
11613 }
static List * on_commits
Definition: tablecmds.c:116
SubTransactionId deleting_subid
Definition: tablecmds.c:113
#define lfirst(lc)
Definition: pg_list.h:106
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:646
void RemoveRelations ( DropStmt drop)

Definition at line 799 of file tablecmds.c.

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

Referenced by ExecDropStmt().

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

Definition at line 2353 of file tablecmds.c.

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

Referenced by ExecRenameStmt().

2354 {
2355  Oid relid;
2356  AttrNumber attnum;
2357  ObjectAddress address;
2358 
2359  /* lock level taken here should match renameatt_internal */
2361  stmt->missing_ok, false,
2363  NULL);
2364 
2365  if (!OidIsValid(relid))
2366  {
2367  ereport(NOTICE,
2368  (errmsg("relation \"%s\" does not exist, skipping",
2369  stmt->relation->relname)));
2370  return InvalidObjectAddress;
2371  }
2372 
2373  attnum =
2374  renameatt_internal(relid,
2375  stmt->subname, /* old att name */
2376  stmt->newname, /* new att name */
2377  interpretInhOption(stmt->relation->inhOpt), /* recursive? */
2378  false, /* recursing? */
2379  0, /* expected inhcount */
2380  stmt->behavior);
2381 
2382  ObjectAddressSubSet(address, RelationRelationId, relid, attnum);
2383 
2384  return address;
2385 }
char * subname
Definition: parsenodes.h:2508
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, bool missing_ok, bool nowait, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:232
InhOption inhOpt
Definition: primnodes.h:75
#define RelationRelationId
Definition: pg_class.h:29
char * newname
Definition: parsenodes.h:2510
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:519
bool interpretInhOption(InhOption inhOpt)
Definition: parse_clause.c:238
char * relname
Definition: primnodes.h:74
bool missing_ok
Definition: parsenodes.h:2512
#define ereport(elevel, rest)
Definition: elog.h:132
RangeVar * relation
Definition: parsenodes.h:2505
#define NOTICE
Definition: elog.h:35
static void RangeVarCallbackForRenameAttribute(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg)
Definition: tablecmds.c:2333
#define NULL
Definition: c.h:215
static AttrNumber renameatt_internal(Oid myrelid, const char *oldattname, const char *newattname, bool recurse, bool recursing, int expected_parents, DropBehavior behavior)
Definition: tablecmds.c:2185
#define ObjectAddressSubSet(addr, class_id, object_id, object_sub_id)
Definition: objectaddress.h:33
#define AccessExclusiveLock
Definition: lockdefs.h:46
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:795
DropBehavior behavior
Definition: parsenodes.h:2511
int16 AttrNumber
Definition: attnum.h:21
ObjectAddress renameatt_type ( RenameStmt stmt)
ObjectAddress RenameConstraint ( RenameStmt stmt)

Definition at line 2490 of file tablecmds.c.

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

Referenced by ExecRenameStmt().

2491 {
2492  Oid relid = InvalidOid;
2493  Oid typid = InvalidOid;
2494 
2495  if (stmt->renameType == OBJECT_DOMCONSTRAINT)
2496  {
2497  Relation rel;
2498  HeapTuple tup;
2499 
2502  tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2503  if (!HeapTupleIsValid(tup))
2504  elog(ERROR, "cache lookup failed for type %u", typid);
2505  checkDomainOwner(tup);
2506  ReleaseSysCache(tup);
2507  heap_close(rel, NoLock);
2508  }
2509  else
2510  {
2511  /* lock level taken here should match rename_constraint_internal */
2513  stmt->missing_ok, false,
2515  NULL);
2516  if (!OidIsValid(relid))
2517  {
2518  ereport(NOTICE,
2519  (errmsg("relation \"%s\" does not exist, skipping",
2520  stmt->relation->relname)));
2521  return InvalidObjectAddress;
2522  }
2523  }
2524 
2525  return
2526  rename_constraint_internal(relid, typid,
2527  stmt->subname,
2528  stmt->newname,
2529  stmt->relation ? interpretInhOption(stmt->relation->inhOpt) : false, /* recursive? */
2530  false, /* recursing? */
2531  0 /* expected inhcount */ );
2532 
2533 }
char * subname
Definition: parsenodes.h:2508
ObjectType renameType
Definition: parsenodes.h:2503
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, bool missing_ok, bool nowait, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:232
InhOption inhOpt
Definition: primnodes.h:75
#define heap_close(r, l)
Definition: heapam.h:97
static ObjectAddress rename_constraint_internal(Oid myrelid, Oid mytypid, const char *oldconname, const char *newconname, bool recurse, bool recursing, int expected_parents)
Definition: tablecmds.c:2391
char * newname
Definition: parsenodes.h:2510
unsigned int Oid
Definition: postgres_ext.h:31
#define TypeRelationId
Definition: pg_type.h:34
#define OidIsValid(objectId)
Definition: c.h:519
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:141
bool interpretInhOption(InhOption inhOpt)
Definition: parse_clause.c:238
char * relname
Definition: primnodes.h:74
bool missing_ok
Definition: parsenodes.h:2512
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:41
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ereport(elevel, rest)
Definition: elog.h:132
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:989
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1234
RangeVar * relation
Definition: parsenodes.h:2505
#define InvalidOid
Definition: postgres_ext.h:36
#define NOTICE
Definition: elog.h:35
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
static void RangeVarCallbackForRenameAttribute(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg)
Definition: tablecmds.c:2333
#define NULL
Definition: c.h:215
void checkDomainOwner(HeapTuple tup)
Definition: typecmds.c:2960
#define AccessExclusiveLock
Definition: lockdefs.h:46
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:795
TypeName * makeTypeNameFromNameList(List *names)
Definition: makefuncs.c:444
#define elog
Definition: elog.h:228
List * object
Definition: parsenodes.h:2506
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:275
ObjectAddress RenameRelation ( RenameStmt stmt)

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

2541 {
2542  Oid relid;
2543  ObjectAddress address;
2544 
2545  /*
2546  * Grab an exclusive lock on the target table, index, sequence, view,
2547  * materialized view, or foreign table, which we will NOT release until
2548  * end of transaction.
2549  *
2550  * Lock level used here should match RenameRelationInternal, to avoid lock
2551  * escalation.
2552  */
2554  stmt->missing_ok, false,
2556  (void *) stmt);
2557 
2558  if (!OidIsValid(relid))
2559  {
2560  ereport(NOTICE,
2561  (errmsg("relation \"%s\" does not exist, skipping",
2562  stmt->relation->relname)));
2563  return InvalidObjectAddress;
2564  }
2565 
2566  /* Do the work */
2567  RenameRelationInternal(relid, stmt->newname, false);
2568 
2569  ObjectAddressSet(address, RelationRelationId, relid);
2570 
2571  return address;
2572 }
void RenameRelationInternal(Oid myrelid, const char *newrelname, bool is_internal)
Definition: tablecmds.c:2584
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, bool missing_ok, bool nowait, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:232
#define RelationRelationId
Definition: pg_class.h:29
char * newname
Definition: parsenodes.h:2510
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:519
char * relname
Definition: primnodes.h:74
bool missing_ok
Definition: parsenodes.h:2512
static void RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg)
Definition: tablecmds.c:11845
#define ereport(elevel, rest)
Definition: elog.h:132
RangeVar * relation
Definition: parsenodes.h:2505
#define NOTICE
Definition: elog.h:35
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define AccessExclusiveLock
Definition: lockdefs.h:46
const ObjectAddress InvalidObjectAddress
int errmsg(const char *fmt,...)
Definition: elog.c:795
void RenameRelationInternal ( Oid  myrelid,
const char *  newrelname,
bool  is_internal 
)

Definition at line 2584 of file tablecmds.c.

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

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

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

Definition at line 2102 of file tablecmds.c.

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

Referenced by acquire_inherited_sample_rows(), and StoreCatalogInheritance1().

2103 {
2104  Relation relationRelation;
2105  HeapTuple tuple;
2106  Form_pg_class classtuple;
2107 
2108  /*
2109  * Fetch a modifiable copy of the tuple, modify it, update pg_class.
2110  */
2111  relationRelation = heap_open(RelationRelationId, RowExclusiveLock);
2112  tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relationId));
2113  if (!HeapTupleIsValid(tuple))
2114  elog(ERROR, "cache lookup failed for relation %u", relationId);
2115  classtuple = (Form_pg_class) GETSTRUCT(tuple);
2116 
2117  if (classtuple->relhassubclass != relhassubclass)
2118  {
2119  classtuple->relhassubclass = relhassubclass;
2120  simple_heap_update(relationRelation, &tuple->t_self, tuple);
2121 
2122  /* keep the catalog indexes up to date */
2123  CatalogUpdateIndexes(relationRelation, tuple);
2124  }
2125  else
2126  {
2127  /* no need to change tuple, but force relcache rebuild anyway */
2129  }
2130 
2131  heap_freetuple(tuple);
2132  heap_close(relationRelation, RowExclusiveLock);
2133 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:631
#define RelationRelationId
Definition: pg_class.h:29
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1306
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:41
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1234
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
void CatalogUpdateIndexes(Relation heapRel, HeapTuple heapTuple)
Definition: indexing.c:157
void simple_heap_update(Relation relation, ItemPointer otid, HeapTuple tup)
Definition: heapam.c:4148
FormData_pg_class * Form_pg_class
Definition: pg_class.h:91
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:150
void CacheInvalidateRelcacheByTuple(HeapTuple classTuple)
Definition: inval.c:1233
#define elog
Definition: elog.h:228