#include "catalog/catalog.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
+#include "catalog/objectaccess.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_conversion.h"
iacls->roleid,
noldmembers, oldmembers,
nnewmembers, newmembers);
+
+ if (isNew)
+ InvokeObjectPostCreateHook(DefaultAclRelationId,
+ HeapTupleGetOid(newtuple), 0);
+ else
+ InvokeObjectPostAlterHook(DefaultAclRelationId,
+ HeapTupleGetOid(newtuple), 0);
}
if (HeapTupleIsValid(tuple))
static void RelationRemoveInheritance(Oid relid);
static void StoreRelCheck(Relation rel, char *ccname, Node *expr,
bool is_validated, bool is_local, int inhcount,
- bool is_no_inherit);
-static void StoreConstraints(Relation rel, List *cooked_constraints);
+ bool is_no_inherit, bool is_internal);
+static void StoreConstraints(Relation rel, List *cooked_constraints,
+ bool is_internal);
static bool MergeWithExistingConstraint(Relation rel, char *ccname, Node *expr,
bool allow_merge, bool is_local,
bool is_no_inherit);
* entry, so the relation must be valid and self-consistent at this point.
* In particular, there are not yet constraints and defaults anywhere.
*/
- StoreConstraints(new_rel_desc, cooked_constraints);
+ StoreConstraints(new_rel_desc, cooked_constraints, is_internal);
/*
* If there's a special on-commit action, remember it
* Store a default expression for column attnum of relation rel.
*/
void
-StoreAttrDefault(Relation rel, AttrNumber attnum, Node *expr)
+StoreAttrDefault(Relation rel, AttrNumber attnum,
+ Node *expr, bool is_internal)
{
char *adbin;
char *adsrc;
* Record dependencies on objects used in the expression, too.
*/
recordDependencyOnExpr(&defobject, expr, NIL, DEPENDENCY_NORMAL);
+
+ /*
+ * Post creation hook for attribute defaults.
+ *
+ * XXX. ALTER TABLE ALTER COLUMN SET/DROP DEFAULT is implemented
+ * with a couple of deletion/creation of the attribute's default entry,
+ * so the callee should check existence of an older version of this
+ * entry if it needs to distinguish.
+ */
+ InvokeObjectPostCreateHookArg(AttrDefaultRelationId,
+ RelationGetRelid(rel), attnum, is_internal);
}
/*
static void
StoreRelCheck(Relation rel, char *ccname, Node *expr,
bool is_validated, bool is_local, int inhcount,
- bool is_no_inherit)
+ bool is_no_inherit, bool is_internal)
{
char *ccbin;
char *ccsrc;
ccsrc, /* Source form of check constraint */
is_local, /* conislocal */
inhcount, /* coninhcount */
- is_no_inherit); /* connoinherit */
+ is_no_inherit, /* connoinherit */
+ is_internal); /* internally constructed? */
pfree(ccbin);
pfree(ccsrc);
* and StoreRelCheck (see AddRelationNewConstraints()).
*/
static void
-StoreConstraints(Relation rel, List *cooked_constraints)
+StoreConstraints(Relation rel, List *cooked_constraints, bool is_internal)
{
int numchecks = 0;
ListCell *lc;
switch (con->contype)
{
case CONSTR_DEFAULT:
- StoreAttrDefault(rel, con->attnum, con->expr);
+ StoreAttrDefault(rel, con->attnum, con->expr, is_internal);
break;
case CONSTR_CHECK:
StoreRelCheck(rel, con->name, con->expr, !con->skip_validation,
- con->is_local, con->inhcount, con->is_no_inherit);
+ con->is_local, con->inhcount,
+ con->is_no_inherit, is_internal);
numchecks++;
break;
default:
* newConstraints: list of Constraint nodes
* allow_merge: TRUE if check constraints may be merged with existing ones
* is_local: TRUE if definition is local, FALSE if it's inherited
+ * is_internal: TRUE if result of some internal process, not a user request
*
* All entries in newColDefaults will be processed. Entries in newConstraints
* will be processed only if they are CONSTR_CHECK type.
List *newColDefaults,
List *newConstraints,
bool allow_merge,
- bool is_local)
+ bool is_local,
+ bool is_internal)
{
List *cookedConstraints = NIL;
TupleDesc tupleDesc;
(IsA(expr, Const) &&((Const *) expr)->constisnull))
continue;
- StoreAttrDefault(rel, colDef->attnum, expr);
+ StoreAttrDefault(rel, colDef->attnum, expr, is_internal);
cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
cooked->contype = CONSTR_DEFAULT;
* OK, store it.
*/
StoreRelCheck(rel, ccname, expr, !cdef->skip_validation, is_local,
- is_local ? 0 : 1, cdef->is_no_inherit);
+ is_local ? 0 : 1, cdef->is_no_inherit, is_internal);
numchecks++;
false, /* already marked primary */
false, /* pg_index entry is OK */
false, /* no old dependencies */
- allow_system_table_mods);
+ allow_system_table_mods,
+ is_internal);
}
else
{
* remove_old_dependencies: if true, remove existing dependencies of index
* on table's columns
* allow_system_table_mods: allow table to be a system catalog
+ * is_internal: index is constructed due to internal process
*/
void
index_constraint_create(Relation heapRelation,
bool mark_as_primary,
bool update_pgindex,
bool remove_old_dependencies,
- bool allow_system_table_mods)
+ bool allow_system_table_mods,
+ bool is_internal)
{
Oid namespaceId = RelationGetNamespace(heapRelation);
ObjectAddress myself,
NULL,
true, /* islocal */
0, /* inhcount */
- true); /* noinherit */
+ true, /* noinherit */
+ is_internal);
/*
* Register the index as internally dependent on the constraint.
{
simple_heap_update(pg_index, &indexTuple->t_self, indexTuple);
CatalogUpdateIndexes(pg_index, indexTuple);
+
+ InvokeObjectPostAlterHookArg(IndexRelationId, indexRelationId, 0,
+ InvalidOid, is_internal);
}
heap_freetuple(indexTuple);
classId, objectId, subId,
(void *) &drop_arg);
}
+
+/*
+ * RunObjectPostAlterHook
+ *
+ * It is entrypoint of OAT_POST_ALTER event
+ */
+void
+RunObjectPostAlterHook(Oid classId, Oid objectId, int subId,
+ Oid auxiliaryId, bool is_internal)
+{
+ ObjectAccessPostAlter pa_arg;
+
+ /* caller should check, but just in case... */
+ Assert(object_access_hook != NULL);
+
+ memset(&pa_arg, 0, sizeof(ObjectAccessPostAlter));
+ pa_arg.auxiliary_id = auxiliaryId;
+ pa_arg.is_internal = is_internal;
+
+ (*object_access_hook)(OAT_POST_ALTER,
+ classId, objectId, subId,
+ (void *) &pa_arg);
+}
const char *conSrc,
bool conIsLocal,
int conInhCount,
- bool conNoInherit)
+ bool conNoInherit,
+ bool is_internal)
{
Relation conDesc;
Oid conOid;
}
/* Post creation hook for new constraint */
- InvokeObjectPostCreateHook(ConstraintRelationId, conOid, 0);
+ InvokeObjectPostCreateHookArg(ConstraintRelationId, conOid, 0,
+ is_internal);
return conOid;
}
/* update the system catalog indexes */
CatalogUpdateIndexes(conDesc, tuple);
+ InvokeObjectPostAlterHook(ConstraintRelationId, conId, 0);
+
heap_freetuple(tuple);
heap_close(conDesc, RowExclusiveLock);
}
*/
}
+ InvokeObjectPostAlterHook(ConstraintRelationId, thisobj.objectId, 0);
+
add_exact_object_address(&thisobj, objsMoved);
}
#include "access/heapam.h"
#include "access/htup_details.h"
#include "catalog/indexing.h"
+#include "catalog/objectaccess.h"
#include "catalog/pg_db_role_setting.h"
#include "utils/fmgroids.h"
#include "utils/rel.h"
CatalogUpdateIndexes(rel, newtuple);
}
+ InvokeObjectPostAlterHookArg(DbRoleSettingRelationId,
+ databaseid, 0, roleid, false);
+
systable_endscan(scan);
/* Close pg_db_role_setting, but keep lock till commit */
/* update the system catalog indexes */
CatalogUpdateIndexes(pg_type_desc, tuple);
+ InvokeObjectPostAlterHook(TypeRelationId, typeOid, 0);
+
heap_freetuple(tuple);
heap_close(pg_type_desc, RowExclusiveLock);
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
+#include "catalog/objectaccess.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_conversion.h"
#include "catalog/pg_event_trigger.h"
simple_heap_update(rel, &oldtup->t_self, newtup);
CatalogUpdateIndexes(rel, newtup);
+ InvokeObjectPostAlterHook(classId, objectId, 0);
+
/* Release memory */
pfree(values);
pfree(nulls);
changeDependencyFor(classId, objid,
NamespaceRelationId, oldNspOid, nspOid);
+ InvokeObjectPostAlterHook(classId, objid, 0);
+
return oldNspOid;
}
pfree(nulls);
pfree(replaces);
}
+
+ InvokeObjectPostAlterHook(classId, objectId, 0);
}
#include "catalog/heap.h"
#include "catalog/index.h"
#include "catalog/namespace.h"
+#include "catalog/objectaccess.h"
#include "catalog/toasting.h"
#include "commands/cluster.h"
#include "commands/matview.h"
* otherwise concurrent executions of RelationGetIndexList could miss indexes.
*/
void
-mark_index_clustered(Relation rel, Oid indexOid)
+mark_index_clustered(Relation rel, Oid indexOid, bool is_internal)
{
HeapTuple indexTuple;
Form_pg_index indexForm;
simple_heap_update(pg_index, &indexTuple->t_self, indexTuple);
CatalogUpdateIndexes(pg_index, indexTuple);
}
+
+ InvokeObjectPostAlterHookArg(IndexRelationId, thisIndexOid, 0,
+ InvalidOid, is_internal);
+
heap_freetuple(indexTuple);
}
/* Mark the correct index as clustered */
if (OidIsValid(indexOid))
- mark_index_clustered(OldHeap, indexOid);
+ mark_index_clustered(OldHeap, indexOid, true);
/* Remember if it's a system catalog */
is_system_catalog = IsSystemRelation(OldHeap);
* rebuild the target's indexes and throw away the transient table.
*/
finish_heap_swap(tableOid, OIDNewHeap, is_system_catalog,
- swap_toast_by_content, false, frozenXid, frozenMulti);
+ swap_toast_by_content, false, true,
+ frozenXid, frozenMulti);
}
static void
swap_relation_files(Oid r1, Oid r2, bool target_is_pg_class,
bool swap_toast_by_content,
+ bool is_internal,
TransactionId frozenXid,
MultiXactId frozenMulti,
Oid *mapped_tables)
CacheInvalidateRelcacheByTuple(reltup2);
}
+ /*
+ * Post alter hook for modified relations. The change to r2 is always
+ * internal, but r1 depends on the invocation context.
+ */
+ InvokeObjectPostAlterHookArg(RelationRelationId, r1, 0,
+ InvalidOid, is_internal);
+ InvokeObjectPostAlterHookArg(RelationRelationId, r2, 0,
+ InvalidOid, true);
+
/*
* If we have toast tables associated with the relations being swapped,
* deal with them too.
relform2->reltoastrelid,
target_is_pg_class,
swap_toast_by_content,
+ is_internal,
frozenXid,
frozenMulti,
mapped_tables);
relform2->reltoastidxid,
target_is_pg_class,
swap_toast_by_content,
+ is_internal,
InvalidTransactionId,
InvalidMultiXactId,
mapped_tables);
bool is_system_catalog,
bool swap_toast_by_content,
bool check_constraints,
+ bool is_internal,
TransactionId frozenXid,
MultiXactId frozenMulti)
{
*/
swap_relation_files(OIDOldHeap, OIDNewHeap,
(OIDOldHeap == RelationRelationId),
- swap_toast_by_content, frozenXid, frozenMulti,
- mapped_tables);
+ swap_toast_by_content, is_internal,
+ frozenXid, frozenMulti, mapped_tables);
/*
* If it's a system catalog, queue an sinval message to flush all
snprintf(NewToastName, NAMEDATALEN, "pg_toast_%u",
OIDOldHeap);
RenameRelationInternal(newrel->rd_rel->reltoastrelid,
- NewToastName);
+ NewToastName, true);
/* ... and its index too */
snprintf(NewToastName, NAMEDATALEN, "pg_toast_%u_index",
OIDOldHeap);
RenameRelationInternal(toastidx,
- NewToastName);
+ NewToastName, true);
}
relation_close(newrel, NoLock);
}
simple_heap_update(rel, &newtup->t_self, newtup);
CatalogUpdateIndexes(rel, newtup);
+ InvokeObjectPostAlterHook(DatabaseRelationId, db_id, 0);
+
/*
* Close pg_database, but keep lock till commit.
*/
/* Update indexes */
CatalogUpdateIndexes(pgdbrel, newtuple);
+ InvokeObjectPostAlterHook(DatabaseRelationId,
+ HeapTupleGetOid(newtuple), 0);
+
systable_endscan(sysscan);
/*
/* Update indexes */
CatalogUpdateIndexes(rel, newtuple);
+ InvokeObjectPostAlterHook(DatabaseRelationId,
+ HeapTupleGetOid(newtuple), 0);
+
systable_endscan(scan);
/* Close pg_database, but keep lock till commit */
newOwnerId);
}
+ InvokeObjectPostAlterHook(DatabaseRelationId, HeapTupleGetOid(tuple), 0);
+
systable_endscan(scan);
/* Close pg_database, but keep lock till commit */
simple_heap_update(tgrel, &tup->t_self, tup);
CatalogUpdateIndexes(tgrel, tup);
+ InvokeObjectPostAlterHook(EventTriggerRelationId,
+ trigoid, 0);
+
/* clean up */
heap_freetuple(tup);
heap_close(tgrel, RowExclusiveLock);
changeDependencyOnOwner(EventTriggerRelationId,
HeapTupleGetOid(tup),
newOwnerId);
+
+ InvokeObjectPostAlterHook(EventTriggerRelationId,
+ HeapTupleGetOid(tup), 0);
}
/*
changeDependencyFor(ExtensionRelationId, extensionOid,
NamespaceRelationId, oldNspOid, nspOid);
+ InvokeObjectPostAlterHook(ExtensionRelationId, extensionOid, 0);
+
return extensionOid;
}
recordDependencyOn(&myself, &otherext, DEPENDENCY_NORMAL);
}
+ InvokeObjectPostAlterHook(ExtensionRelationId, extensionOid, 0);
+
/*
* Finally, execute the update script file
*/
extension_config_remove(extension.objectId, object.objectId);
}
+ InvokeObjectPostAlterHook(ExtensionRelationId, extension.objectId, 0);
+
/*
* If get_object_address() opened the relation for us, we close it to keep
* the reference count correct - but we retain any locks acquired by
HeapTupleGetOid(tup),
newOwnerId);
}
+
+ InvokeObjectPostAlterHook(ForeignDataWrapperRelationId,
+ HeapTupleGetOid(tup), 0);
}
/*
changeDependencyOnOwner(ForeignServerRelationId, HeapTupleGetOid(tup),
newOwnerId);
}
+
+ InvokeObjectPostAlterHook(ForeignServerRelationId,
+ HeapTupleGetOid(tup), 0);
}
/*
}
}
+ InvokeObjectPostAlterHook(ForeignDataWrapperRelationId, fdwId, 0);
+
heap_close(rel, RowExclusiveLock);
return fdwId;
simple_heap_update(rel, &tp->t_self, tp);
CatalogUpdateIndexes(rel, tp);
+ InvokeObjectPostAlterHook(ForeignServerRelationId, srvId, 0);
+
heap_freetuple(tp);
heap_close(rel, RowExclusiveLock);
simple_heap_update(rel, &tup->t_self, tup);
CatalogUpdateIndexes(rel, tup);
+ InvokeObjectPostAlterHook(ProcedureRelationId, funcOid, 0);
+
heap_close(rel, NoLock);
heap_freetuple(tup);
* Swap the physical files of the target and transient tables, then
* rebuild the target's indexes and throw away the transient table.
*/
- finish_heap_swap(matviewOid, OIDNewHeap, false, false, true, RecentXmin,
- ReadNextMultiXactId());
+ finish_heap_swap(matviewOid, OIDNewHeap, false, false, true, true,
+ RecentXmin, ReadNextMultiXactId());
RelationCacheInvalidateEntry(matviewOid);
}
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
}
+ /* Post create hook of this access method operator */
+ InvokeObjectPostCreateHook(AccessMethodOperatorRelationId,
+ entryoid, 0);
}
heap_close(rel, RowExclusiveLock);
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
}
+ /* Post create hook of access method procedure */
+ InvokeObjectPostCreateHook(AccessMethodProcedureRelationId,
+ entryoid, 0);
}
heap_close(rel, RowExclusiveLock);
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
+#include "catalog/objectaccess.h"
#include "catalog/pg_namespace.h"
#include "commands/dbcommands.h"
#include "commands/schemacmds.h"
simple_heap_update(rel, &tup->t_self, tup);
CatalogUpdateIndexes(rel, tup);
+ InvokeObjectPostAlterHook(NamespaceRelationId, HeapTupleGetOid(tup), 0);
+
heap_close(rel, NoLock);
heap_freetuple(tup);
newOwnerId);
}
+ InvokeObjectPostAlterHook(NamespaceRelationId,
+ HeapTupleGetOid(tup), 0);
}
#include "access/xlogutils.h"
#include "catalog/dependency.h"
#include "catalog/namespace.h"
+#include "catalog/objectaccess.h"
#include "catalog/pg_type.h"
#include "commands/defrem.h"
#include "commands/sequence.h"
if (owned_by)
process_owned_by(seqrel, owned_by);
+ InvokeObjectPostAlterHook(RelationRelationId, relid, 0);
+
relation_close(seqrel, NoLock);
return relid;
*/
if (rawDefaults || stmt->constraints)
AddRelationNewConstraints(rel, rawDefaults, stmt->constraints,
- true, true);
+ true, true, false);
/*
* Clean up. We keep lock on new relation (although it shouldn't be
recordDependencyOn(&childobject, &parentobject, DEPENDENCY_NORMAL);
+ /*
+ * Post creation hook of this inheritance. Since object_access_hook
+ * doesn't take multiple object identifiers, we relay oid of parent
+ * relation using auxiliary_id argument.
+ */
+ InvokeObjectPostAlterHookArg(InheritsRelationId,
+ relationId, 0,
+ parentOid, false);
+
/*
* Mark the parent as having subclasses.
*/
/* keep system catalog indexes current */
CatalogUpdateIndexes(attrelation, atttup);
+ InvokeObjectPostAlterHook(RelationRelationId, myrelid, attnum);
+
heap_freetuple(atttup);
heap_close(attrelation, RowExclusiveLock);
|| con->contype == CONSTRAINT_UNIQUE
|| con->contype == CONSTRAINT_EXCLUSION))
/* rename the index; this renames the constraint as well */
- RenameRelationInternal(con->conindid, newconname);
+ RenameRelationInternal(con->conindid, newconname, false);
else
RenameConstraintById(constraintOid, newconname);
}
/* Do the work */
- RenameRelationInternal(relid, stmt->newname);
+ RenameRelationInternal(relid, stmt->newname, false);
return relid;
}
* sequence, AFAIK there's no need for it to be there.
*/
void
-RenameRelationInternal(Oid myrelid, const char *newrelname)
+RenameRelationInternal(Oid myrelid, const char *newrelname, bool is_internal)
{
Relation targetrelation;
Relation relrelation; /* for RELATION relation */
/* keep the system catalog indexes current */
CatalogUpdateIndexes(relrelation, reltup);
+ InvokeObjectPostAlterHookArg(RelationRelationId, myrelid, 0,
+ InvalidOid, is_internal);
+
heap_freetuple(reltup);
heap_close(relrelation, RowExclusiveLock);
* interest in letting this code work on system catalogs.
*/
finish_heap_swap(tab->relid, OIDNewHeap,
- false, false, true, RecentXmin,
+ false, false, true,
+ !OidIsValid(tab->newTableSpace),
+ RecentXmin,
ReadNextMultiXactId());
}
else
* This function is intended for CREATE TABLE, so it processes a
* _list_ of defaults, but we just do one.
*/
- AddRelationNewConstraints(rel, list_make1(rawEnt), NIL, false, true);
+ AddRelationNewConstraints(rel, list_make1(rawEnt), NIL,
+ false, true, false);
/* Make the additional catalog changes visible */
CommandCounterIncrement();
CatalogUpdateIndexes(attr_rel, tuple);
}
+ InvokeObjectPostAlterHook(RelationRelationId,
+ RelationGetRelid(rel), attnum);
+
heap_close(attr_rel, RowExclusiveLock);
}
tab->new_notnull = true;
}
+ InvokeObjectPostAlterHook(RelationRelationId,
+ RelationGetRelid(rel), attnum);
+
heap_close(attr_rel, RowExclusiveLock);
}
* This function is intended for CREATE TABLE, so it processes a
* _list_ of defaults, but we just do one.
*/
- AddRelationNewConstraints(rel, list_make1(rawEnt), NIL, false, true);
+ AddRelationNewConstraints(rel, list_make1(rawEnt), NIL,
+ false, true, false);
}
}
/* keep system catalog indexes current */
CatalogUpdateIndexes(attrelation, tuple);
+ InvokeObjectPostAlterHook(RelationRelationId,
+ RelationGetRelid(rel),
+ attrtuple->attnum);
heap_freetuple(tuple);
heap_close(attrelation, RowExclusiveLock);
repl_repl[Anum_pg_attribute_attoptions - 1] = true;
newtuple = heap_modify_tuple(tuple, RelationGetDescr(attrelation),
repl_val, repl_null, repl_repl);
- ReleaseSysCache(tuple);
/* Update system catalog. */
simple_heap_update(attrelation, &newtuple->t_self, newtuple);
CatalogUpdateIndexes(attrelation, newtuple);
+
+ InvokeObjectPostAlterHook(RelationRelationId,
+ RelationGetRelid(rel),
+ attrtuple->attnum);
heap_freetuple(newtuple);
+ ReleaseSysCache(tuple);
+
heap_close(attrelation, RowExclusiveLock);
}
/* keep system catalog indexes current */
CatalogUpdateIndexes(attrelation, tuple);
+ InvokeObjectPostAlterHook(RelationRelationId,
+ RelationGetRelid(rel),
+ attrtuple->attnum);
+
heap_freetuple(tuple);
heap_close(attrelation, RowExclusiveLock);
ereport(NOTICE,
(errmsg("ALTER TABLE / ADD CONSTRAINT USING INDEX will rename index \"%s\" to \"%s\"",
indexName, constraintName)));
- RenameRelationInternal(index_oid, constraintName);
+ RenameRelationInternal(index_oid, constraintName, false);
}
/* Extra checks needed if making primary key */
stmt->primary,
true, /* update pg_index */
true, /* remove old dependencies */
- allowSystemTableMods);
+ allowSystemTableMods,
+ false); /* is_internal */
index_close(indexRel, NoLock);
}
newcons = AddRelationNewConstraints(rel, NIL,
list_make1(copyObject(constr)),
recursing, /* allow_merge */
- !recursing); /* is_local */
+ !recursing, /* is_local */
+ is_readd); /* is_internal */
/* Add each to-be-validated constraint to Phase 3's queue */
foreach(lcon, newcons)
NULL,
true, /* islocal */
0, /* inhcount */
- true); /* isnoinherit */
+ true, /* isnoinherit */
+ false); /* is_internal */
/*
* Create the triggers that will enforce the constraint.
copy_con->convalidated = true;
simple_heap_update(conrel, ©Tuple->t_self, copyTuple);
CatalogUpdateIndexes(conrel, copyTuple);
+
+ InvokeObjectPostAlterHook(ConstraintRelationId,
+ HeapTupleGetOid(tuple), 0);
+
heap_freetuple(copyTuple);
}
*/
RemoveStatistics(RelationGetRelid(rel), attnum);
+ InvokeObjectPostAlterHook(RelationRelationId,
+ RelationGetRelid(rel), attnum);
+
/*
* Update the default, if present, by brute force --- remove and re-add
* the default. Probably unsafe to take shortcuts, since the new version
RemoveAttrDefault(RelationGetRelid(rel), attnum, DROP_RESTRICT, true,
true);
- StoreAttrDefault(rel, attnum, defaultexpr);
+ StoreAttrDefault(rel, attnum, defaultexpr, true);
}
/* Cleanup */
newtuple = heap_modify_tuple(tuple, RelationGetDescr(attrel),
repl_val, repl_null, repl_repl);
- ReleaseSysCache(tuple);
simple_heap_update(attrel, &newtuple->t_self, newtuple);
CatalogUpdateIndexes(attrel, newtuple);
+ InvokeObjectPostAlterHook(RelationRelationId,
+ RelationGetRelid(rel),
+ atttableform->attnum);
+
+ ReleaseSysCache(tuple);
+
heap_close(attrel, RowExclusiveLock);
heap_freetuple(newtuple);
}
}
+ InvokeObjectPostAlterHook(RelationRelationId, relationOid, 0);
+
ReleaseSysCache(tuple);
heap_close(class_rel, RowExclusiveLock);
relation_close(target_rel, NoLock);
check_index_is_clusterable(rel, indexOid, false, lockmode);
/* And do the work */
- mark_index_clustered(rel, indexOid);
+ mark_index_clustered(rel, indexOid, false);
}
/*
static void
ATExecDropCluster(Relation rel, LOCKMODE lockmode)
{
- mark_index_clustered(rel, InvalidOid);
+ mark_index_clustered(rel, InvalidOid, false);
}
/*
CatalogUpdateIndexes(pgclass, newtuple);
+ InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), 0);
+
heap_freetuple(newtuple);
ReleaseSysCache(tuple);
CatalogUpdateIndexes(pgclass, newtuple);
+ InvokeObjectPostAlterHookArg(RelationRelationId,
+ RelationGetRelid(toastrel), 0,
+ InvalidOid, true);
+
heap_freetuple(newtuple);
ReleaseSysCache(tuple);
if (newTableSpace == oldTableSpace ||
(newTableSpace == MyDatabaseTableSpace && oldTableSpace == 0))
{
+ InvokeObjectPostAlterHook(RelationRelationId,
+ RelationGetRelid(rel), 0);
+
relation_close(rel, NoLock);
return;
}
simple_heap_update(pg_class, &tuple->t_self, tuple);
CatalogUpdateIndexes(pg_class, tuple);
+ InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), 0);
+
heap_freetuple(tuple);
heap_close(pg_class, RowExclusiveLock);
RelationRelationId,
RelationGetRelid(parent_rel));
+ /*
+ * Post alter hook of this inherits. Since object_access_hook doesn't
+ * take multiple object identifiers, we relay oid of parent relation
+ * using auxiliary_id argument.
+ */
+ InvokeObjectPostAlterHookArg(InheritsRelationId,
+ RelationGetRelid(rel), 0,
+ RelationGetRelid(parent_rel), false);
+
/* keep our lock on the parent relation until commit */
heap_close(parent_rel, NoLock);
}
((Form_pg_class) GETSTRUCT(classtuple))->reloftype = typeid;
simple_heap_update(relationRelation, &classtuple->t_self, classtuple);
CatalogUpdateIndexes(relationRelation, classtuple);
+
+ InvokeObjectPostAlterHook(RelationRelationId, relid, 0);
+
heap_freetuple(classtuple);
heap_close(relationRelation, RowExclusiveLock);
((Form_pg_class) GETSTRUCT(tuple))->reloftype = InvalidOid;
simple_heap_update(relationRelation, &tuple->t_self, tuple);
CatalogUpdateIndexes(relationRelation, tuple);
+
+ InvokeObjectPostAlterHook(RelationRelationId, relid, 0);
+
heap_freetuple(tuple);
heap_close(relationRelation, RowExclusiveLock);
}
simple_heap_update(ftrel, &tuple->t_self, tuple);
CatalogUpdateIndexes(ftrel, tuple);
+ InvokeObjectPostAlterHook(ForeignTableRelationId,
+ RelationGetRelid(rel), 0);
+
heap_close(ftrel, RowExclusiveLock);
heap_freetuple(tuple);
NameStr(classForm->relname));
add_exact_object_address(&thisobj, objsMoved);
+
+ InvokeObjectPostAlterHook(RelationRelationId, relOid, 0);
}
heap_freetuple(classTup);
simple_heap_update(rel, &newtuple->t_self, newtuple);
CatalogUpdateIndexes(rel, newtuple);
+ InvokeObjectPostAlterHook(TableSpaceRelationId, tspId, 0);
+
heap_close(rel, NoLock);
return tspId;
/* Update system catalog. */
simple_heap_update(rel, &newtuple->t_self, newtuple);
CatalogUpdateIndexes(rel, newtuple);
+
+ InvokeObjectPostAlterHook(TableSpaceRelationId, HeapTupleGetOid(tup), 0);
+
heap_freetuple(newtuple);
/* Conclude heap scan. */
NULL,
true, /* islocal */
0, /* inhcount */
- true); /* isnoinherit */
+ true, /* isnoinherit */
+ isInternal); /* is_internal */
}
/*
DEPENDENCY_NORMAL);
/* Post creation hook for new trigger */
- InvokeObjectPostCreateHook(TriggerRelationId, trigoid, 0);
+ InvokeObjectPostCreateHookArg(TriggerRelationId, trigoid, 0,
+ isInternal);
/* Keep lock on target rel until end of xact */
heap_close(rel, NoLock);
/* keep system catalog indexes current */
CatalogUpdateIndexes(tgrel, tuple);
+ InvokeObjectPostAlterHook(TriggerRelationId,
+ HeapTupleGetOid(tuple), 0);
+
/*
* Invalidate relation's relcache entry so that other backends (and
* this one too!) are sent SI message to make them rebuild relcache
changed = true;
}
+
+ InvokeObjectPostAlterHook(TriggerRelationId,
+ HeapTupleGetOid(tuple), 0);
}
systable_endscan(tgscan);
CatalogUpdateIndexes(rel, newtup);
+ InvokeObjectPostAlterHook(TSDictionaryRelationId, dictId, 0);
+
/*
* NOTE: because we only support altering the options, not the template,
* there is no need to update dependencies. This might have to change if
/* Update dependencies */
makeConfigurationDependencies(tup, true, relMap);
+ InvokeObjectPostAlterHook(TSConfigMapRelationId,
+ HeapTupleGetOid(tup), 0);
+
heap_close(relMap, RowExclusiveLock);
ReleaseSysCache(tup);
#include "catalog/dependency.h"
#include "catalog/heap.h"
#include "catalog/indexing.h"
+#include "catalog/objectaccess.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_constraint.h"
stmt->newValNeighbor, stmt->newValIsAfter,
stmt->skipIfExists);
+ InvokeObjectPostAlterHook(TypeRelationId, enum_type_oid, 0);
+
ReleaseSysCache(tup);
return enum_type_oid;
defaultExpr,
true); /* Rebuild is true */
+ InvokeObjectPostAlterHook(TypeRelationId, domainoid, 0);
+
/* Clean up */
heap_close(rel, NoLock);
heap_freetuple(newtuple);
CatalogUpdateIndexes(typrel, tup);
+ InvokeObjectPostAlterHook(TypeRelationId, domainoid, 0);
+
/* Clean up */
heap_freetuple(tup);
heap_close(typrel, RowExclusiveLock);
copy_con->convalidated = true;
simple_heap_update(conrel, ©Tuple->t_self, copyTuple);
CatalogUpdateIndexes(conrel, copyTuple);
+
+ InvokeObjectPostAlterHook(ConstraintRelationId,
+ HeapTupleGetOid(copyTuple), 0);
+
heap_freetuple(copyTuple);
systable_endscan(scan);
ccsrc, /* Source form of check constraint */
true, /* is local */
0, /* inhcount */
- false); /* connoinherit */
+ false, /* connoinherit */
+ false); /* is_internal */
/*
* Return the compiled constraint expression so the calling routine can
* RenameRelationInternal will call RenameTypeInternal automatically.
*/
if (typTup->typtype == TYPTYPE_COMPOSITE)
- RenameRelationInternal(typTup->typrelid, newTypeName);
+ RenameRelationInternal(typTup->typrelid, newTypeName, false);
else
RenameTypeInternal(typeOid, newTypeName,
typTup->typnamespace);
/* Update owner dependency reference */
changeDependencyOnOwner(TypeRelationId, typeOid, newOwnerId);
+ InvokeObjectPostAlterHook(TypeRelationId, typeOid, 0);
+
/* If it has an array type, update that too */
if (OidIsValid(typTup->typarray))
AlterTypeOwnerInternal(typTup->typarray, newOwnerId, false);
*
* hasDependEntry should be TRUE if type is expected to have a pg_shdepend
* entry (ie, it's not a table rowtype nor an array type).
+ * is_primary_ops should be TRUE if this function is invoked with user's
+ * direct operation (e.g, shdepReassignOwned). Elsewhere,
*/
void
AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId,
if (OidIsValid(typTup->typarray))
AlterTypeOwnerInternal(typTup->typarray, newOwnerId, false);
+ InvokeObjectPostAlterHook(TypeRelationId, typeOid, 0);
+
/* Clean up */
heap_close(rel, RowExclusiveLock);
}
elog(ERROR, "failed to change schema dependency for type %s",
format_type_be(typeOid));
+ InvokeObjectPostAlterHook(TypeRelationId, typeOid, 0);
+
heap_freetuple(tup);
heap_close(rel, RowExclusiveLock);
/* Update indexes */
CatalogUpdateIndexes(pg_authid_rel, new_tuple);
+ InvokeObjectPostAlterHook(AuthIdRelationId, roleid, 0);
+
ReleaseSysCache(tuple);
heap_freetuple(new_tuple);
CatalogUpdateIndexes(rel, newtuple);
+ InvokeObjectPostAlterHook(AuthIdRelationId, roleid, 0);
+
ReleaseSysCache(oldtuple);
/*
changed = true;
}
+ InvokeObjectPostAlterHook(RewriteRelationId,
+ HeapTupleGetOid(ruletup), 0);
+
heap_freetuple(ruletup);
heap_close(pg_rewrite_desc, RowExclusiveLock);
List *newColDefaults,
List *newConstraints,
bool allow_merge,
- bool is_local);
+ bool is_local,
+ bool is_internal);
-extern void StoreAttrDefault(Relation rel, AttrNumber attnum, Node *expr);
+extern void StoreAttrDefault(Relation rel, AttrNumber attnum,
+ Node *expr, bool is_internal);
extern Node *cookDefault(ParseState *pstate,
Node *raw_default,
bool mark_as_primary,
bool update_pgindex,
bool remove_old_dependencies,
- bool allow_system_table_mods);
+ bool allow_system_table_mods,
+ bool is_internal);
extern void index_drop(Oid indexId, bool concurrent);
* OAT_DROP should be invoked just before deletion of objects; typically
* deleteOneObject(). Its arguments are packed within ObjectAccessDrop.
*
+ * OAT_POST_ALTER should be invoked just after the object is altered,
+ * but before the command counter is incremented. An extension using the
+ * hook can use SnapshotNow and SnapshotSelf to get the old and new
+ * versions of the tuple.
+ *
* Other types may be added in the future.
*/
typedef enum ObjectAccessType
} ObjectAccessDrop;
/*
- * Hook, and a macro to invoke it.
+ * Arguments of OAT_POST_ALTER event
*/
+typedef struct
+{
+ /*
+ * This identifier is used when system catalog takes two IDs
+ * to identify a particular tuple of the catalog.
+ * It is only used when the caller want to identify an entry
+ * of pg_inherits, pg_db_role_setting or pg_user_mapping.
+ * Elsewhere, InvalidOid should be set.
+ */
+ Oid auxiliary_id;
+
+ /*
+ * If this flag is set, the user hasn't requested that the object be
+ * altered, but we're doing it anyway for some internal reason.
+ * Permissions-checking hooks may want to skip checks if, say, we're
+ * alter the constraints of a temporary heap during CLUSTER.
+ */
+ bool is_internal;
+} ObjectAccessPostAlter;
+
+/* Plugin provides a hook function matching this signature. */
typedef void (*object_access_hook_type) (ObjectAccessType access,
Oid classId,
Oid objectId,
int subId,
void *arg);
+/* Plugin sets this variable to a suitable hook function. */
extern PGDLLIMPORT object_access_hook_type object_access_hook;
+/* Core code uses these functions to call the hook (see macros below). */
extern void RunObjectPostCreateHook(Oid classId, Oid objectId, int subId,
bool is_internal);
extern void RunObjectDropHook(Oid classId, Oid objectId, int subId,
int dropflags);
+extern void RunObjectPostAlterHook(Oid classId, Oid objectId, int subId,
+ Oid auxiliaryId, bool is_internal);
+
+/*
+ * The following macros are wrappers around the functions above; these should
+ * normally be used to invoke the hook in lieu of calling the above functions
+ * directly.
+ */
#define InvokeObjectPostCreateHook(classId,objectId,subId) \
InvokeObjectPostCreateHookArg((classId),(objectId),(subId),false)
(dropflags)); \
} while(0)
+#define InvokeObjectPostAlterHook(classId,objectId,subId) \
+ InvokeObjectPostAlterHookArg((classId),(objectId),(subId), \
+ InvalidOid,false)
+#define InvokeObjectPostAlterHookArg(classId,objectId,subId, \
+ auxiliaryId,is_internal) \
+ do { \
+ if (object_access_hook) \
+ RunObjectPostAlterHook((classId),(objectId),(subId), \
+ (auxiliaryId),(is_internal)); \
+ } while(0)
+
#endif /* OBJECTACCESS_H */
const char *conSrc,
bool conIsLocal,
int conInhCount,
- bool conNoInherit);
+ bool conNoInherit,
+ bool is_internal);
extern void RemoveConstraintById(Oid conId);
extern void RenameConstraintById(Oid conId, const char *newname);
bool verbose, int freeze_min_age, int freeze_table_age);
extern void check_index_is_clusterable(Relation OldHeap, Oid indexOid,
bool recheck, LOCKMODE lockmode);
-extern void mark_index_clustered(Relation rel, Oid indexOid);
+extern void mark_index_clustered(Relation rel, Oid indexOid, bool is_internal);
extern Oid make_new_heap(Oid OIDOldHeap, Oid NewTableSpace);
extern void finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap,
bool is_system_catalog,
bool swap_toast_by_content,
bool check_constraints,
+ bool is_internal,
TransactionId frozenXid,
MultiXactId frozenMulti);
extern Oid RenameRelation(RenameStmt *stmt);
extern void RenameRelationInternal(Oid myrelid,
- const char *newrelname);
+ const char *newrelname, bool is_internal);
extern void find_composite_type_dependencies(Oid typeOid,
Relation origRelation,