mirror of https://github.com/citusdata/citus.git
130 lines
3.5 KiB
C
130 lines
3.5 KiB
C
/*-------------------------------------------------------------------------
|
|
*
|
|
* master_truncate.c
|
|
*
|
|
* Routine for truncating local data after a table has been distributed.
|
|
*
|
|
* Copyright (c) Citus Data, Inc.
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
|
|
#include "postgres.h"
|
|
|
|
#include <stddef.h>
|
|
|
|
#include "commands/tablecmds.h"
|
|
#include "commands/trigger.h"
|
|
#include "distributed/commands/utility_hook.h"
|
|
#include "distributed/master_metadata_utility.h"
|
|
#include "distributed/master_protocol.h"
|
|
#include "distributed/multi_executor.h"
|
|
#include "distributed/multi_join_order.h"
|
|
#include "distributed/pg_dist_partition.h"
|
|
#include "distributed/resource_lock.h"
|
|
#include "utils/builtins.h"
|
|
#include "utils/lsyscache.h"
|
|
#include "utils/rel.h"
|
|
|
|
|
|
static List * TruncateTaskList(Oid relationId);
|
|
|
|
|
|
/* exports for SQL callable functions */
|
|
PG_FUNCTION_INFO_V1(citus_truncate_trigger);
|
|
|
|
|
|
/*
|
|
* citus_truncate_trigger is called as a trigger when a distributed
|
|
* table is truncated.
|
|
*/
|
|
Datum
|
|
citus_truncate_trigger(PG_FUNCTION_ARGS)
|
|
{
|
|
if (!CALLED_AS_TRIGGER(fcinfo))
|
|
{
|
|
ereport(ERROR, (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
|
|
errmsg("must be called as trigger")));
|
|
}
|
|
|
|
TriggerData *triggerData = (TriggerData *) fcinfo->context;
|
|
Relation truncatedRelation = triggerData->tg_relation;
|
|
Oid relationId = RelationGetRelid(truncatedRelation);
|
|
char partitionMethod = PartitionMethod(relationId);
|
|
|
|
if (!EnableDDLPropagation)
|
|
{
|
|
PG_RETURN_DATUM(PointerGetDatum(NULL));
|
|
}
|
|
|
|
if (partitionMethod == DISTRIBUTE_BY_APPEND)
|
|
{
|
|
Oid schemaId = get_rel_namespace(relationId);
|
|
char *schemaName = get_namespace_name(schemaId);
|
|
char *relationName = get_rel_name(relationId);
|
|
|
|
DirectFunctionCall3(master_drop_all_shards,
|
|
ObjectIdGetDatum(relationId),
|
|
CStringGetTextDatum(relationName),
|
|
CStringGetTextDatum(schemaName));
|
|
}
|
|
else
|
|
{
|
|
List *taskList = TruncateTaskList(relationId);
|
|
|
|
ExecuteUtilityTaskListWithoutResults(taskList);
|
|
}
|
|
|
|
PG_RETURN_DATUM(PointerGetDatum(NULL));
|
|
}
|
|
|
|
|
|
/*
|
|
* TruncateTaskList returns a list of tasks to execute a TRUNCATE on a
|
|
* distributed table. This is handled separately from other DDL commands
|
|
* because we handle it via the TRUNCATE trigger, which is called whenever
|
|
* a truncate cascades.
|
|
*/
|
|
static List *
|
|
TruncateTaskList(Oid relationId)
|
|
{
|
|
List *shardIntervalList = LoadShardIntervalList(relationId);
|
|
ListCell *shardIntervalCell = NULL;
|
|
List *taskList = NIL;
|
|
int taskId = 1;
|
|
|
|
Oid schemaId = get_rel_namespace(relationId);
|
|
char *schemaName = get_namespace_name(schemaId);
|
|
char *relationName = get_rel_name(relationId);
|
|
|
|
/* lock metadata before getting placement lists */
|
|
LockShardListMetadata(shardIntervalList, ShareLock);
|
|
|
|
foreach(shardIntervalCell, shardIntervalList)
|
|
{
|
|
ShardInterval *shardInterval = (ShardInterval *) lfirst(shardIntervalCell);
|
|
uint64 shardId = shardInterval->shardId;
|
|
StringInfo shardQueryString = makeStringInfo();
|
|
char *shardName = pstrdup(relationName);
|
|
|
|
AppendShardIdToName(&shardName, shardId);
|
|
|
|
appendStringInfo(shardQueryString, "TRUNCATE TABLE %s CASCADE",
|
|
quote_qualified_identifier(schemaName, shardName));
|
|
|
|
Task *task = CitusMakeNode(Task);
|
|
task->jobId = INVALID_JOB_ID;
|
|
task->taskId = taskId++;
|
|
task->taskType = DDL_TASK;
|
|
task->queryString = shardQueryString->data;
|
|
task->dependentTaskList = NULL;
|
|
task->replicationModel = REPLICATION_MODEL_INVALID;
|
|
task->anchorShardId = shardId;
|
|
task->taskPlacementList = FinalizedShardPlacementList(shardId);
|
|
|
|
taskList = lappend(taskList, task);
|
|
}
|
|
|
|
return taskList;
|
|
}
|