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
pull/4304/head
Hanefi Onaldi 2020-11-09 12:03:59 +03:00 committed by GitHub
parent 5d5966f700
commit d3019f1b6d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 33 additions and 1 deletions

View File

@ -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)

View File

@ -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,