#include "catalog/pg_opclass.h"
#include "catalog/pg_partitioned_table.h"
#include "catalog/pg_statistic.h"
-#include "catalog/pg_statistic_ext.h"
#include "catalog/pg_subscription_rel.h"
#include "catalog/pg_tablespace.h"
#include "catalog/pg_type.h"
#include "parser/parse_collate.h"
#include "parser/parse_expr.h"
#include "parser/parse_relation.h"
+#include "storage/lmgr.h"
#include "storage/predicate.h"
#include "storage/smgr.h"
#include "utils/acl.h"
static FormData_pg_attribute a1 = {
0, {"ctid"}, TIDOID, 0, sizeof(ItemPointerData),
SelfItemPointerAttributeNumber, 0, -1, -1,
- false, 'p', 's', true, false, false, true, 0
+ false, 'p', 's', true, false, '\0', false, true, 0
};
static FormData_pg_attribute a2 = {
0, {"oid"}, OIDOID, 0, sizeof(Oid),
ObjectIdAttributeNumber, 0, -1, -1,
- true, 'p', 'i', true, false, false, true, 0
+ true, 'p', 'i', true, false, '\0', false, true, 0
};
static FormData_pg_attribute a3 = {
0, {"xmin"}, XIDOID, 0, sizeof(TransactionId),
MinTransactionIdAttributeNumber, 0, -1, -1,
- true, 'p', 'i', true, false, false, true, 0
+ true, 'p', 'i', true, false, '\0', false, true, 0
};
static FormData_pg_attribute a4 = {
0, {"cmin"}, CIDOID, 0, sizeof(CommandId),
MinCommandIdAttributeNumber, 0, -1, -1,
- true, 'p', 'i', true, false, false, true, 0
+ true, 'p', 'i', true, false, '\0', false, true, 0
};
static FormData_pg_attribute a5 = {
0, {"xmax"}, XIDOID, 0, sizeof(TransactionId),
MaxTransactionIdAttributeNumber, 0, -1, -1,
- true, 'p', 'i', true, false, false, true, 0
+ true, 'p', 'i', true, false, '\0', false, true, 0
};
static FormData_pg_attribute a6 = {
0, {"cmax"}, CIDOID, 0, sizeof(CommandId),
MaxCommandIdAttributeNumber, 0, -1, -1,
- true, 'p', 'i', true, false, false, true, 0
+ true, 'p', 'i', true, false, '\0', false, true, 0
};
/*
static FormData_pg_attribute a7 = {
0, {"tableoid"}, OIDOID, 0, sizeof(Oid),
TableOidAttributeNumber, 0, -1, -1,
- true, 'p', 'i', true, false, false, true, 0
+ true, 'p', 'i', true, false, '\0', false, true, 0
};
static const Form_pg_attribute SysAtt[] = {&a1, &a2, &a3, &a4, &a5, &a6, &a7};
case RELKIND_VIEW:
case RELKIND_COMPOSITE_TYPE:
case RELKIND_FOREIGN_TABLE:
+ case RELKIND_PARTITIONED_TABLE:
create_storage = false;
/*
values[Anum_pg_attribute_attalign - 1] = CharGetDatum(new_attribute->attalign);
values[Anum_pg_attribute_attnotnull - 1] = BoolGetDatum(new_attribute->attnotnull);
values[Anum_pg_attribute_atthasdef - 1] = BoolGetDatum(new_attribute->atthasdef);
+ values[Anum_pg_attribute_attidentity - 1] = CharGetDatum(new_attribute->attidentity);
values[Anum_pg_attribute_attisdropped - 1] = BoolGetDatum(new_attribute->attisdropped);
values[Anum_pg_attribute_attislocal - 1] = BoolGetDatum(new_attribute->attislocal);
values[Anum_pg_attribute_attinhcount - 1] = Int32GetDatum(new_attribute->attinhcount);
if (oncommit != ONCOMMIT_NOOP)
register_on_commit_action(relid, oncommit);
- if (relpersistence == RELPERSISTENCE_UNLOGGED)
- {
- Assert(relkind == RELKIND_RELATION || relkind == RELKIND_MATVIEW ||
- relkind == RELKIND_TOASTVALUE ||
- relkind == RELKIND_PARTITIONED_TABLE);
-
+ /*
+ * Unlogged objects need an init fork, except for partitioned tables which
+ * have no storage at all.
+ */
+ if (relpersistence == RELPERSISTENCE_UNLOGGED &&
+ relkind != RELKIND_PARTITIONED_TABLE)
heap_create_init_fork(new_rel_desc);
- }
/*
* ok, the relation has been cataloged, so close our relations and return
void
heap_create_init_fork(Relation rel)
{
+ Assert(rel->rd_rel->relkind == RELKIND_RELATION ||
+ rel->rd_rel->relkind == RELKIND_MATVIEW ||
+ rel->rd_rel->relkind == RELKIND_TOASTVALUE);
RelationOpenSmgr(rel);
smgrcreate(rel->rd_smgr, INIT_FORKNUM, false);
log_smgrcreate(&rel->rd_smgr->smgr_rnode.node, INIT_FORKNUM);
heap_close(attr_rel, RowExclusiveLock);
if (attnum > 0)
- {
RemoveStatistics(relid, attnum);
- RemoveStatisticsExt(relid, attnum);
- }
relation_close(rel, NoLock);
}
heap_drop_with_catalog(Oid relid)
{
Relation rel;
- Oid parentOid;
- Relation parent = NULL;
-
- /*
- * Open and lock the relation.
- */
- rel = relation_open(relid, AccessExclusiveLock);
+ HeapTuple tuple;
+ Oid parentOid = InvalidOid;
/*
- * If the relation is a partition, we must grab exclusive lock on its
- * parent because we need to update its partition descriptor. We must take
- * a table lock strong enough to prevent all queries on the parent from
- * proceeding until we commit and send out a shared-cache-inval notice
- * that will make them update their partition descriptor. Sometimes, doing
- * this is cycles spent uselessly, especially if the parent will be
- * dropped as part of the same command anyway.
+ * To drop a partition safely, we must grab exclusive lock on its parent,
+ * because another backend might be about to execute a query on the parent
+ * table. If it relies on previously cached partition descriptor, then it
+ * could attempt to access the just-dropped relation as its partition. We
+ * must therefore take a table lock strong enough to prevent all queries
+ * on the table from proceeding until we commit and send out a
+ * shared-cache-inval notice that will make them update their index lists.
*/
- if (rel->rd_rel->relispartition)
+ tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
+ if (((Form_pg_class) GETSTRUCT(tuple))->relispartition)
{
parentOid = get_partition_parent(relid);
- parent = heap_open(parentOid, AccessExclusiveLock);
+ LockRelationOid(parentOid, AccessExclusiveLock);
}
+ ReleaseSysCache(tuple);
+
+ /*
+ * Open and lock the relation.
+ */
+ rel = relation_open(relid, AccessExclusiveLock);
+
/*
* There can no longer be anyone *else* touching the relation, but we
* might still have open queries or cursors, or pending trigger events, in
*/
if (rel->rd_rel->relkind != RELKIND_VIEW &&
rel->rd_rel->relkind != RELKIND_COMPOSITE_TYPE &&
- rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE)
+ rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
+ rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
{
RelationDropStorage(rel);
}
* delete statistics
*/
RemoveStatistics(relid, 0);
- RemoveStatisticsExt(relid, 0);
/*
* delete attribute tuples
*/
DeleteRelationTuple(relid);
- if (parent)
+ if (OidIsValid(parentOid))
{
/*
* Invalidate the parent's relcache so that the partition is no longer
* included in its partition descriptor.
*/
- CacheInvalidateRelcache(parent);
- heap_close(parent, NoLock); /* keep the lock */
+ CacheInvalidateRelcacheByRelid(parentOid);
+ /* keep the lock */
}
}
}
-/*
- * RemoveStatisticsExt --- remove entries in pg_statistic_ext for a relation
- *
- * If attnum is zero, remove all entries for rel; else remove only the
- * one(s) involving that column.
- */
-void
-RemoveStatisticsExt(Oid relid, AttrNumber attnum)
-{
- Relation pgstatisticext;
- SysScanDesc scan;
- ScanKeyData key;
- HeapTuple tuple;
-
- /*
- * Scan pg_statistic_ext to delete relevant tuples
- */
- pgstatisticext = heap_open(StatisticExtRelationId, RowExclusiveLock);
-
- ScanKeyInit(&key,
- Anum_pg_statistic_ext_starelid,
- BTEqualStrategyNumber, F_OIDEQ,
- ObjectIdGetDatum(relid));
-
- scan = systable_beginscan(pgstatisticext,
- StatisticExtRelidIndexId,
- true, NULL, 1, &key);
-
- while (HeapTupleIsValid(tuple = systable_getnext(scan)))
- {
- bool delete = false;
-
- if (attnum == 0)
- delete = true;
- else if (attnum != 0)
- {
- Form_pg_statistic_ext staForm;
- int i;
-
- /*
- * Decode the stakeys array and delete any stats that involve the
- * specified column.
- */
- staForm = (Form_pg_statistic_ext) GETSTRUCT(tuple);
- for (i = 0; i < staForm->stakeys.dim1; i++)
- {
- if (staForm->stakeys.values[i] == attnum)
- {
- delete = true;
- break;
- }
- }
- }
-
- if (delete)
- {
- CatalogTupleDelete(pgstatisticext, &tuple->t_self);
- deleteDependencyRecordsFor(StatisticExtRelationId,
- HeapTupleGetOid(tuple),
- false);
- }
- }
-
- systable_endscan(scan);
-
- heap_close(pgstatisticext, RowExclusiveLock);
-}
-
-
/*
* RelationTruncateIndexes - truncate all indexes associated
* with the heap relation to zero tuples.