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.
pull/3900/head
Sait Talha Nisanci 2020-05-18 11:50:22 +03:00
parent 8ce8683ac4
commit 0819b79631
6 changed files with 65 additions and 33 deletions

View File

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

View File

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

View File

@ -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;
}

View File

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

View File

@ -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 */

View File

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