Support TRUNCATE for foreign tables

truncate-foreign-tables
Ahmet Gedemenli 2022-02-14 15:55:53 +03:00
parent 8a3544b4d9
commit c107111d5e
3 changed files with 68 additions and 9 deletions

View File

@ -45,6 +45,7 @@
/* Local functions forward declarations for unsupported command checks */ /* Local functions forward declarations for unsupported command checks */
static void ErrorIfUnsupportedTruncateStmt(TruncateStmt *truncateStatement); static void ErrorIfUnsupportedTruncateStmt(TruncateStmt *truncateStatement);
static List * UndistributeForeignTablesBeforeTruncate(TruncateStmt *truncateStatement);
static void ExecuteTruncateStmtSequentialIfNecessary(TruncateStmt *command); static void ExecuteTruncateStmtSequentialIfNecessary(TruncateStmt *command);
static void EnsurePartitionTableNotReplicatedForTruncate(TruncateStmt *truncateStatement); static void EnsurePartitionTableNotReplicatedForTruncate(TruncateStmt *truncateStatement);
static void LockTruncatedRelationMetadataInWorkers(TruncateStmt *truncateStatement); static void LockTruncatedRelationMetadataInWorkers(TruncateStmt *truncateStatement);
@ -242,13 +243,36 @@ EnsureLocalTableCanBeTruncated(Oid relationId)
* done before standard process utility is called for truncate * done before standard process utility is called for truncate
* command. * command.
*/ */
void List *
PreprocessTruncateStatement(TruncateStmt *truncateStatement) PreprocessTruncateStatement(TruncateStmt *truncateStatement)
{ {
ErrorIfUnsupportedTruncateStmt(truncateStatement); ErrorIfUnsupportedTruncateStmt(truncateStatement);
List *undistributedForeignCitusLocalTables =
UndistributeForeignTablesBeforeTruncate(truncateStatement);
EnsurePartitionTableNotReplicatedForTruncate(truncateStatement); EnsurePartitionTableNotReplicatedForTruncate(truncateStatement);
ExecuteTruncateStmtSequentialIfNecessary(truncateStatement); ExecuteTruncateStmtSequentialIfNecessary(truncateStatement);
LockTruncatedRelationMetadataInWorkers(truncateStatement); LockTruncatedRelationMetadataInWorkers(truncateStatement);
return undistributedForeignCitusLocalTables;
}
/*
* AddForeignTablesToMetadataAfterTruncate takes a list of rangeVar, that contains the
* foreign Citus Local Tables that are undistributed before TRUNCATE. This function
* adds the given relations to metadata.
*/
void
AddForeignTablesToMetadataAfterTruncate(List *undistributedForeignCitusLocalTables)
{
RangeVar *rangeVar = NULL;
foreach_ptr(rangeVar, undistributedForeignCitusLocalTables)
{
Oid relationId = RangeVarGetRelid(rangeVar, NoLock, false);
CreateCitusLocalTable(relationId, true, true);
}
} }
@ -266,16 +290,41 @@ ErrorIfUnsupportedTruncateStmt(TruncateStmt *truncateStatement)
Oid relationId = RangeVarGetRelid(rangeVar, NoLock, false); Oid relationId = RangeVarGetRelid(rangeVar, NoLock, false);
ErrorIfIllegallyChangingKnownShard(relationId); ErrorIfIllegallyChangingKnownShard(relationId);
}
}
if (IsCitusTable(relationId) && IsForeignTable(relationId))
/*
* UndistributeForeignTablesBeforeTruncate takes a TruncateStmt and undistributes the
* foreign tables in that statement. Returns the RangeVar list of undistributed tables.
*/
static List *
UndistributeForeignTablesBeforeTruncate(TruncateStmt *truncateStatement)
{
List *undistributedTables = NIL;
List *relationList = truncateStatement->relations;
RangeVar *rangeVar = NULL;
foreach_ptr(rangeVar, relationList)
{
Oid relationId = RangeVarGetRelid(rangeVar, NoLock, false);
if (IsForeignTable(relationId) &&
IsCitusTableType(relationId, CITUS_LOCAL_TABLE))
{ {
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), ereport(DEBUG1, (errmsg("undistributing foreign table %s",
errmsg("truncating distributed foreign tables is " generate_qualified_relation_name(relationId)),
"currently unsupported"), errdetail("Will be added to metadata after TRUNCATE")));
errhint("Consider undistributing table before TRUNCATE, " TableConversionParameters params = {
"and then distribute or add to metadata again"))); .relationId = relationId,
.cascadeViaForeignKeys = true,
.suppressNoticeMessages = true
};
UndistributeTable(&params);
undistributedTables = lappend(undistributedTables, rangeVar);
} }
} }
return undistributedTables;
} }

View File

@ -499,9 +499,11 @@ ProcessUtilityInternal(PlannedStmt *pstmt,
ErrorIfDistributedAlterSeqOwnedBy((AlterSeqStmt *) parsetree); ErrorIfDistributedAlterSeqOwnedBy((AlterSeqStmt *) parsetree);
} }
List *undistributedForeignCitusLocalTables = NIL;
if (IsA(parsetree, TruncateStmt)) if (IsA(parsetree, TruncateStmt))
{ {
PreprocessTruncateStatement((TruncateStmt *) parsetree); undistributedForeignCitusLocalTables =
PreprocessTruncateStatement((TruncateStmt *) parsetree);
} }
/* /*
@ -786,6 +788,12 @@ ProcessUtilityInternal(PlannedStmt *pstmt,
PostprocessVacuumStmt(vacuumStmt, queryString); PostprocessVacuumStmt(vacuumStmt, queryString);
} }
if (IsA(parsetree, TruncateStmt) &&
list_length(undistributedForeignCitusLocalTables) != 0)
{
AddForeignTablesToMetadataAfterTruncate(undistributedForeignCitusLocalTables);
}
if (!IsDropCitusExtensionStmt(parsetree) && !IsA(parsetree, DropdbStmt)) if (!IsDropCitusExtensionStmt(parsetree) && !IsA(parsetree, DropdbStmt))
{ {
/* /*

View File

@ -466,7 +466,9 @@ extern bool ConstrTypeUsesIndex(ConstrType constrType);
/* truncate.c - forward declarations */ /* truncate.c - forward declarations */
extern void PreprocessTruncateStatement(TruncateStmt *truncateStatement); extern List * PreprocessTruncateStatement(TruncateStmt *truncateStatement);
extern void AddForeignTablesToMetadataAfterTruncate(
List *undistributedForeignCitusLocalTables);
/* type.c - forward declarations */ /* type.c - forward declarations */
extern List * PreprocessCompositeTypeStmt(Node *stmt, const char *queryString, extern List * PreprocessCompositeTypeStmt(Node *stmt, const char *queryString,