/*------------------------------------------------------------------------- * * drop_distributed_table.c * Routines related to dropping distributed relations from a trigger. * * Copyright (c) Citus Data, Inc. * *------------------------------------------------------------------------- */ #include "postgres.h" #include "miscadmin.h" #include "distributed/commands/utility_hook.h" #include "distributed/master_metadata_utility.h" #include "distributed/master_protocol.h" #include "distributed/metadata_sync.h" #include "distributed/worker_transaction.h" #include "utils/builtins.h" #include "utils/lsyscache.h" /* local function forward declarations */ static void MasterRemoveDistributedTableMetadataFromWorkers(Oid relationId, char *schemaName, char *tableName); /* exports for SQL callable functions */ PG_FUNCTION_INFO_V1(master_drop_distributed_table_metadata); PG_FUNCTION_INFO_V1(master_remove_partition_metadata); PG_FUNCTION_INFO_V1(master_remove_distributed_table_metadata_from_workers); /* * master_drop_distributed_table_metadata UDF is a stub UDF to install Citus flawlessly. * Otherwise we need to delete them from our sql files, which is confusing and not a * common operation in the code-base. * * This function is basically replaced with * master_remove_distributed_table_metadata_from_workers() followed by * master_remove_partition_metadata(). */ Datum master_drop_distributed_table_metadata(PG_FUNCTION_ARGS) { ereport(INFO, (errmsg("this function is deprecated and no longer is used"))); PG_RETURN_VOID(); } /* * master_remove_partition_metadata removes the entry of the specified distributed * table from pg_dist_partition. */ Datum master_remove_partition_metadata(PG_FUNCTION_ARGS) { Oid relationId = PG_GETARG_OID(0); text *schemaNameText = PG_GETARG_TEXT_P(1); text *tableNameText = PG_GETARG_TEXT_P(2); char *schemaName = text_to_cstring(schemaNameText); char *tableName = text_to_cstring(tableNameText); CheckCitusVersion(ERROR); /* * The SQL_DROP trigger calls this function even for tables that are * not distributed. In that case, silently ignore. This is not very * user-friendly, but this function is really only meant to be called * from the trigger. */ if (!IsDistributedTable(relationId) || !EnableDDLPropagation) { PG_RETURN_VOID(); } EnsureCoordinator(); CheckTableSchemaNameForDrop(relationId, &schemaName, &tableName); DeletePartitionRow(relationId); PG_RETURN_VOID(); } /* * master_remove_distributed_table_metadata_from_workers removes the entry of the * specified distributed table from pg_dist_partition and drops the table from * the workers if needed. */ Datum master_remove_distributed_table_metadata_from_workers(PG_FUNCTION_ARGS) { Oid relationId = PG_GETARG_OID(0); text *schemaNameText = PG_GETARG_TEXT_P(1); text *tableNameText = PG_GETARG_TEXT_P(2); char *schemaName = text_to_cstring(schemaNameText); char *tableName = text_to_cstring(tableNameText); CheckCitusVersion(ERROR); CheckTableSchemaNameForDrop(relationId, &schemaName, &tableName); MasterRemoveDistributedTableMetadataFromWorkers(relationId, schemaName, tableName); PG_RETURN_VOID(); } /* * MasterRemoveDistributedTableMetadataFromWorkers drops the table and removes * all the metadata belonging the distributed table in the worker nodes * with metadata. The function doesn't drop the tables that are * the shards on the workers. * * The function is a no-op for non-distributed tables and clusters that don't * have any workers with metadata. Also, the function errors out if called * from a worker node. */ static void MasterRemoveDistributedTableMetadataFromWorkers(Oid relationId, char *schemaName, char *tableName) { /* * The SQL_DROP trigger calls this function even for tables that are * not distributed. In that case, silently ignore. This is not very * user-friendly, but this function is really only meant to be called * from the trigger. */ if (!IsDistributedTable(relationId) || !EnableDDLPropagation) { return; } EnsureCoordinator(); if (!ShouldSyncTableMetadata(relationId)) { return; } /* drop the distributed table metadata on the workers */ char *deleteDistributionCommand = DistributionDeleteCommand(schemaName, tableName); SendCommandToWorkersWithMetadata(deleteDistributionCommand); }