From d3019f1b6d153177cc9d64fa4b8190a655e7bc57 Mon Sep 17 00:00:00 2001 From: Hanefi Onaldi Date: Mon, 9 Nov 2020 12:03:59 +0300 Subject: [PATCH] Introduce foreach_ptr_modify macro (#4303) If one wishes to iterate through a List and insert list elements in PG13, it is not safe to use for_each_ptr as the List representation in PostgreSQL no longer linked lists, but arrays, and it is possible that the whole array is repalloc'ed if ther is not sufficient space available. See postgres commit 1cff1b95ab6ddae32faa3efe0d95a820dbfdc164 for more information --- src/backend/distributed/metadata/dependency.c | 2 +- src/include/distributed/listutils.h | 32 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/backend/distributed/metadata/dependency.c b/src/backend/distributed/metadata/dependency.c index 6dacf2cc3..81106207b 100644 --- a/src/backend/distributed/metadata/dependency.c +++ b/src/backend/distributed/metadata/dependency.c @@ -1097,7 +1097,7 @@ GetDependingViews(Oid relationId) List *dependingViews = NIL; List *nodeQueue = list_make1(tableNode); ViewDependencyNode *node = NULL; - foreach_ptr(node, nodeQueue) + foreach_ptr_append(node, nodeQueue) { ViewDependencyNode *dependingNode = NULL; foreach_ptr(dependingNode, node->dependingNodes) diff --git a/src/include/distributed/listutils.h b/src/include/distributed/listutils.h index ddc14c7a2..3a177f7d9 100644 --- a/src/include/distributed/listutils.h +++ b/src/include/distributed/listutils.h @@ -80,6 +80,38 @@ typedef struct ListCellAndListWrapper (((var) = lfirst_oid(var ## CellDoNotUse)) || true); \ var ## CellDoNotUse = lnext_compat(l, var ## CellDoNotUse)) +/* + * foreach_ptr_append - + * a convenience macro which loops through a pointer List and can append list + * elements without needing a ListCell or and index variable, just a declared + * pointer variable to store the iterated values. + * + * PostgreSQL 13 changed the representation of Lists to expansible arrays, + * not chains of cons-cells. This changes the costs for accessing and + * mutating List contents. Therefore different implementations are provided. + * + * For more information, see postgres commit with sha + * 1cff1b95ab6ddae32faa3efe0d95a820dbfdc164 + */ +#if PG_VERSION_NUM >= PG_VERSION_13 + +/* + * How it works: + * - An index is declared with the name {var}PositionDoNotUse and used + * throughout the for loop using ## to concat. + * - To assign to var it needs to be done in the condition of the for loop, + * because we cannot use the initializer since the index variable is + * declared there. + * - || true is used to always enter the loop even if var is NULL. + */ +#define foreach_ptr_append(var, l) \ + for (int var ## PositionDoNotUse = 0; \ + (var ## PositionDoNotUse) < list_length(l) && \ + (((var) = list_nth(l, var ## PositionDoNotUse)) || true); \ + var ## PositionDoNotUse ++) +#else +#define foreach_ptr_append(var, l) foreach_ptr(var, l) +#endif /* utility functions declaration shared within this module */ extern List * SortList(List *pointerList,