From 0819b796318fdd88749cbe095f40beb12a03b633 Mon Sep 17 00:00:00 2001 From: Sait Talha Nisanci Date: Mon, 18 May 2020 11:50:22 +0300 Subject: [PATCH] introduce list compat macros Pass the list to lnext API lnext API now expects the list as well. The commit on Postgres that introduced the change: 1cff1b95ab6ddae32faa3efe0d95a820dbfdc164 lnext_compat and list_delete_cell_compat macros are introduced so that we can use these macros in the codebase without having to use #if directives in the codebase. Related commit on postgres: 1cff1b95ab6ddae32faa3efe0d95a820dbfdc164 Command to search in postgres: git log --all --grep="list_delete_cell" add ListCellAndListWrapper When iterating a list in separate function calls, we need both the list and the current cell starting from PG13, therefore ListCellAndListWrapper is added to store both as a wrapper. Use ListCellAndListWrapper in foreign key test udfs As we iterate a list in these udfs using a functionContext, we need to use the wrapper to be able to access both the list and the current cell. --- src/backend/distributed/commands/multi_copy.c | 10 +++-- .../distributed/operations/node_protocol.c | 15 +++++--- .../planner/intermediate_result_pruning.c | 10 +++-- .../test/foreign_key_relationship_query.c | 38 +++++++++++-------- src/include/distributed/listutils.h | 18 +++++++-- src/include/distributed/version_compat.h | 7 ++++ 6 files changed, 65 insertions(+), 33 deletions(-) diff --git a/src/backend/distributed/commands/multi_copy.c b/src/backend/distributed/commands/multi_copy.c index f8580a6b9..e1399e4e9 100644 --- a/src/backend/distributed/commands/multi_copy.c +++ b/src/backend/distributed/commands/multi_copy.c @@ -753,18 +753,20 @@ static List * RemoveOptionFromList(List *optionList, char *optionName) { ListCell *optionCell = NULL; + #if PG_VERSION_NUM < PG_VERSION_13 ListCell *previousCell = NULL; - + #endif foreach(optionCell, optionList) { DefElem *option = (DefElem *) lfirst(optionCell); if (strncmp(option->defname, optionName, NAMEDATALEN) == 0) { - return list_delete_cell(optionList, optionCell, previousCell); + return list_delete_cell_compat(optionList, optionCell, previousCell); } - + #if PG_VERSION_NUM < PG_VERSION_13 previousCell = optionCell; + #endif } return optionList; @@ -1423,7 +1425,7 @@ ColumnCoercionPaths(TupleDesc destTupleDescriptor, TupleDesc inputTupleDescripto ConversionPathForTypes(inputTupleType, destTupleType, &coercePaths[columnIndex]); - currentColumnName = lnext(currentColumnName); + currentColumnName = lnext_compat(columnNameList, currentColumnName); if (currentColumnName == NULL) { diff --git a/src/backend/distributed/operations/node_protocol.c b/src/backend/distributed/operations/node_protocol.c index 552c439ca..e3afea866 100644 --- a/src/backend/distributed/operations/node_protocol.c +++ b/src/backend/distributed/operations/node_protocol.c @@ -75,6 +75,7 @@ int NextPlacementId = 0; static List * GetTableReplicaIdentityCommand(Oid relationId); static Datum WorkerNodeGetDatum(WorkerNode *workerNode, TupleDesc tupleDescriptor); + /* exports for SQL callable functions */ PG_FUNCTION_INFO_V1(master_get_table_metadata); PG_FUNCTION_INFO_V1(master_get_table_ddl_events); @@ -221,8 +222,10 @@ master_get_table_ddl_events(PG_FUNCTION_ARGS) /* allocate DDL statements, and then save position in DDL statements */ List *tableDDLEventList = GetTableDDLEvents(relationId, includeSequenceDefaults); tableDDLEventCell = list_head(tableDDLEventList); - - functionContext->user_fctx = tableDDLEventCell; + ListCellAndListWrapper* wrapper = palloc0(sizeof(ListCellAndListWrapper)); + wrapper->list = tableDDLEventList; + wrapper->listCell = tableDDLEventCell; + functionContext->user_fctx = wrapper; MemoryContextSwitchTo(oldContext); } @@ -235,13 +238,13 @@ master_get_table_ddl_events(PG_FUNCTION_ARGS) */ functionContext = SRF_PERCALL_SETUP(); - tableDDLEventCell = (ListCell *) functionContext->user_fctx; - if (tableDDLEventCell != NULL) + ListCellAndListWrapper* wrapper = (ListCellAndListWrapper *) functionContext->user_fctx; + if (wrapper->listCell != NULL) { - char *ddlStatement = (char *) lfirst(tableDDLEventCell); + char *ddlStatement = (char *) lfirst(wrapper->listCell); text *ddlStatementText = cstring_to_text(ddlStatement); - functionContext->user_fctx = lnext(tableDDLEventCell); + wrapper->listCell = lnext_compat(wrapper->list, wrapper->listCell); SRF_RETURN_NEXT(functionContext, PointerGetDatum(ddlStatementText)); } diff --git a/src/backend/distributed/planner/intermediate_result_pruning.c b/src/backend/distributed/planner/intermediate_result_pruning.c index 2156e3469..4b7aa5a87 100644 --- a/src/backend/distributed/planner/intermediate_result_pruning.c +++ b/src/backend/distributed/planner/intermediate_result_pruning.c @@ -370,18 +370,20 @@ RemoveLocalNodeFromWorkerList(List *workerNodeList) int32 localGroupId = GetLocalGroupId(); ListCell *workerNodeCell = NULL; + #if PG_VERSION_NUM < PG_VERSION_13 ListCell *prev = NULL; + #endif foreach(workerNodeCell, workerNodeList) { WorkerNode *workerNode = (WorkerNode *) lfirst(workerNodeCell); if (workerNode->groupId == localGroupId) { - return list_delete_cell(workerNodeList, workerNodeCell, prev); + return list_delete_cell_compat(workerNodeList, workerNodeCell, prev); } - - prev = workerNodeCell; } - + #if PG_VERSION_NUM < PG_VERSION_13 + prev = workerNodeCell; + #endif return workerNodeList; } diff --git a/src/backend/distributed/test/foreign_key_relationship_query.c b/src/backend/distributed/test/foreign_key_relationship_query.c index d2cb207d4..d93938fa5 100644 --- a/src/backend/distributed/test/foreign_key_relationship_query.c +++ b/src/backend/distributed/test/foreign_key_relationship_query.c @@ -14,8 +14,9 @@ #include "fmgr.h" #include "funcapi.h" +#include "distributed/listutils.h" #include "distributed/metadata_cache.h" - +#include "distributed/version_compat.h" /* these functions are only exported in the regression tests */ PG_FUNCTION_INFO_V1(get_referencing_relation_id_list); @@ -47,10 +48,12 @@ get_referencing_relation_id_list(PG_FUNCTION_ARGS) MemoryContextSwitchTo(functionContext->multi_call_memory_ctx); List *refList = list_copy( cacheEntry->referencingRelationsViaForeignKey); - MemoryContextSwitchTo(oldContext); - + ListCellAndListWrapper* wrapper = palloc0(sizeof(ListCellAndListWrapper)); foreignRelationCell = list_head(refList); - functionContext->user_fctx = foreignRelationCell; + wrapper->list = refList; + wrapper->listCell = foreignRelationCell; + functionContext->user_fctx = wrapper; + MemoryContextSwitchTo(oldContext); } /* @@ -61,12 +64,12 @@ get_referencing_relation_id_list(PG_FUNCTION_ARGS) */ functionContext = SRF_PERCALL_SETUP(); - foreignRelationCell = (ListCell *) functionContext->user_fctx; - if (foreignRelationCell != NULL) + ListCellAndListWrapper* wrapper = (ListCellAndListWrapper *) functionContext->user_fctx; + if (wrapper->listCell != NULL) { - Oid refId = lfirst_oid(foreignRelationCell); + Oid refId = lfirst_oid(wrapper->listCell); - functionContext->user_fctx = lnext(foreignRelationCell); + wrapper->listCell = lnext_compat(wrapper->list, wrapper->listCell); SRF_RETURN_NEXT(functionContext, PointerGetDatum(refId)); } @@ -102,10 +105,12 @@ get_referenced_relation_id_list(PG_FUNCTION_ARGS) MemoryContext oldContext = MemoryContextSwitchTo(functionContext->multi_call_memory_ctx); List *refList = list_copy(cacheEntry->referencedRelationsViaForeignKey); - MemoryContextSwitchTo(oldContext); - foreignRelationCell = list_head(refList); - functionContext->user_fctx = foreignRelationCell; + ListCellAndListWrapper* wrapper = palloc0(sizeof(ListCellAndListWrapper)); + wrapper->list = refList; + wrapper->listCell = foreignRelationCell; + functionContext->user_fctx = wrapper; + MemoryContextSwitchTo(oldContext); } /* @@ -116,12 +121,13 @@ get_referenced_relation_id_list(PG_FUNCTION_ARGS) */ functionContext = SRF_PERCALL_SETUP(); - foreignRelationCell = (ListCell *) functionContext->user_fctx; - if (foreignRelationCell != NULL) - { - Oid refId = lfirst_oid(foreignRelationCell); + ListCellAndListWrapper* wrapper = (ListCellAndListWrapper *) functionContext->user_fctx; - functionContext->user_fctx = lnext(foreignRelationCell); + if (wrapper->listCell != NULL) + { + Oid refId = lfirst_oid(wrapper->listCell); + + wrapper->listCell = lnext_compat(wrapper->list, wrapper->listCell); SRF_RETURN_NEXT(functionContext, PointerGetDatum(refId)); } diff --git a/src/include/distributed/listutils.h b/src/include/distributed/listutils.h index 26819f00a..e37addbe1 100644 --- a/src/include/distributed/listutils.h +++ b/src/include/distributed/listutils.h @@ -18,8 +18,20 @@ #include "nodes/pg_list.h" #include "utils/array.h" #include "utils/hsearch.h" +#include "distributed/version_compat.h" +/* + * ListCellAndListWrapper stores a list and list cell. + * This struct is used for functionContext. When iterating a list + * in separate function calls, we need both the list and the current cell. + * Therefore this wrapper stores both of them. + */ +typedef struct ListCellAndListWrapper { + List *list; + ListCell *listCell; +} ListCellAndListWrapper; + /* * foreach_ptr - * a convenience macro which loops through a pointer list without needing a @@ -39,7 +51,7 @@ for (ListCell *(var ## CellDoNotUse) = list_head(l); \ (var ## CellDoNotUse) != NULL && \ (((var) = lfirst(var ## CellDoNotUse)) || true); \ - var ## CellDoNotUse = lnext(var ## CellDoNotUse)) + var ## CellDoNotUse = lnext_compat(l, var ## CellDoNotUse)) /* @@ -52,7 +64,7 @@ for (ListCell *(var ## CellDoNotUse) = list_head(l); \ (var ## CellDoNotUse) != NULL && \ (((var) = lfirst_int(var ## CellDoNotUse)) || true); \ - var ## CellDoNotUse = lnext(var ## CellDoNotUse)) + var ## CellDoNotUse = lnext_compat(l, var ## CellDoNotUse)) /* @@ -65,7 +77,7 @@ for (ListCell *(var ## CellDoNotUse) = list_head(l); \ (var ## CellDoNotUse) != NULL && \ (((var) = lfirst_oid(var ## CellDoNotUse)) || true); \ - var ## CellDoNotUse = lnext(var ## CellDoNotUse)) + var ## CellDoNotUse = lnext_compat(l, var ## CellDoNotUse)) /* utility functions declaration shared within this module */ diff --git a/src/include/distributed/version_compat.h b/src/include/distributed/version_compat.h index fdee6498b..a1fc4dfcc 100644 --- a/src/include/distributed/version_compat.h +++ b/src/include/distributed/version_compat.h @@ -24,6 +24,13 @@ #include "optimizer/optimizer.h" #endif +#if PG_VERSION_NUM >= PG_VERSION_13 +#define lnext_compat(l, r) lnext(l, r) +#define list_delete_cell_compat(l,c,p) list_delete_cell(l,c) +#else /* pre PG13 */ +#define lnext_compat(l, r) lnext(r) +#define list_delete_cell_compat(l,c,p) list_delete_cell(l,c,p) +#endif #if PG_VERSION_NUM >= PG_VERSION_12 #define MakeSingleTupleTableSlotCompat MakeSingleTupleTableSlot