mirror of https://github.com/citusdata/citus.git
133 lines
4.1 KiB
C
133 lines
4.1 KiB
C
/*-------------------------------------------------------------------------
|
|
*
|
|
* worker_drop_protocol.c
|
|
*
|
|
* Routines for dropping distributed tables and their metadata on worker nodes.
|
|
*
|
|
* Copyright (c) Citus Data, Inc.
|
|
*
|
|
* $Id$
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
|
|
#include "postgres.h"
|
|
|
|
#include "access/genam.h"
|
|
#include "access/heapam.h"
|
|
#include "access/xact.h"
|
|
#include "catalog/dependency.h"
|
|
#include "catalog/pg_foreign_server.h"
|
|
#include "distributed/citus_ruleutils.h"
|
|
#include "distributed/distribution_column.h"
|
|
#include "distributed/listutils.h"
|
|
#include "distributed/metadata_utility.h"
|
|
#include "distributed/coordinator_protocol.h"
|
|
#include "distributed/metadata_cache.h"
|
|
#include "foreign/foreign.h"
|
|
#include "utils/builtins.h"
|
|
#include "utils/fmgroids.h"
|
|
|
|
|
|
PG_FUNCTION_INFO_V1(worker_drop_distributed_table);
|
|
|
|
|
|
/*
|
|
* worker_drop_distributed_table drops the distributed table with the given oid,
|
|
* then, removes the associated rows from pg_dist_partition, pg_dist_shard and
|
|
* pg_dist_placement. The function also drops the server for foreign tables.
|
|
*
|
|
* Note that drop fails if any dependent objects are present for any of the
|
|
* distributed tables. Also, shard placements of the distributed tables are
|
|
* not dropped as in the case of "DROP TABLE distributed_table;" command.
|
|
*
|
|
* The function errors out if the input relation Oid is not a regular or foreign table.
|
|
* The function is meant to be called only by the coordinator, therefore requires
|
|
* superuser privileges.
|
|
*/
|
|
Datum
|
|
worker_drop_distributed_table(PG_FUNCTION_ARGS)
|
|
{
|
|
text *relationName = PG_GETARG_TEXT_P(0);
|
|
Oid relationId = ResolveRelationId(relationName, true);
|
|
|
|
ObjectAddress distributedTableObject = { InvalidOid, InvalidOid, 0 };
|
|
char relationKind = '\0';
|
|
|
|
CheckCitusVersion(ERROR);
|
|
EnsureSuperUser();
|
|
|
|
if (!OidIsValid(relationId))
|
|
{
|
|
ereport(NOTICE, (errmsg("relation %s does not exist, skipping",
|
|
text_to_cstring(relationName))));
|
|
PG_RETURN_VOID();
|
|
}
|
|
|
|
List *shardList = LoadShardList(relationId);
|
|
|
|
/* first check the relation type */
|
|
Relation distributedRelation = relation_open(relationId, AccessShareLock);
|
|
relationKind = distributedRelation->rd_rel->relkind;
|
|
EnsureRelationKindSupported(relationId);
|
|
|
|
/* close the relation since we do not need anymore */
|
|
relation_close(distributedRelation, AccessShareLock);
|
|
|
|
/* prepare distributedTableObject for dropping the table */
|
|
distributedTableObject.classId = RelationRelationId;
|
|
distributedTableObject.objectId = relationId;
|
|
distributedTableObject.objectSubId = 0;
|
|
|
|
/* drop the server for the foreign relations */
|
|
if (relationKind == RELKIND_FOREIGN_TABLE)
|
|
{
|
|
ObjectAddresses *objects = new_object_addresses();
|
|
ObjectAddress foreignServerObject = { InvalidOid, InvalidOid, 0 };
|
|
ForeignTable *foreignTable = GetForeignTable(relationId);
|
|
Oid serverId = foreignTable->serverid;
|
|
|
|
/* prepare foreignServerObject for dropping the server */
|
|
foreignServerObject.classId = ForeignServerRelationId;
|
|
foreignServerObject.objectId = serverId;
|
|
foreignServerObject.objectSubId = 0;
|
|
|
|
/* add the addresses that are going to be dropped */
|
|
add_exact_object_address(&distributedTableObject, objects);
|
|
add_exact_object_address(&foreignServerObject, objects);
|
|
|
|
/* drop both the table and the server */
|
|
performMultipleDeletions(objects, DROP_RESTRICT,
|
|
PERFORM_DELETION_INTERNAL);
|
|
}
|
|
else
|
|
{
|
|
/* drop the table with cascade since other tables may be referring to it */
|
|
performDeletion(&distributedTableObject, DROP_CASCADE,
|
|
PERFORM_DELETION_INTERNAL);
|
|
}
|
|
|
|
/* iterate over shardList to delete the corresponding rows */
|
|
uint64 *shardIdPointer = NULL;
|
|
foreach_ptr(shardIdPointer, shardList)
|
|
{
|
|
uint64 shardId = *shardIdPointer;
|
|
|
|
List *shardPlacementList = ShardPlacementList(shardId);
|
|
ShardPlacement *placement = NULL;
|
|
foreach_ptr(placement, shardPlacementList)
|
|
{
|
|
/* delete the row from pg_dist_placement */
|
|
DeleteShardPlacementRow(placement->placementId);
|
|
}
|
|
|
|
/* delete the row from pg_dist_shard */
|
|
DeleteShardRow(shardId);
|
|
}
|
|
|
|
/* delete the row from pg_dist_partition */
|
|
DeletePartitionRow(relationId);
|
|
|
|
PG_RETURN_VOID();
|
|
}
|