diff --git a/src/backend/distributed/utils/citus_nodefuncs.c b/src/backend/distributed/utils/citus_nodefuncs.c index dc6160b6f..4cf380403 100644 --- a/src/backend/distributed/utils/citus_nodefuncs.c +++ b/src/backend/distributed/utils/citus_nodefuncs.c @@ -44,6 +44,8 @@ static const char *CitusNodeTagNamesD[] = { const char **CitusNodeTagNames = CitusNodeTagNamesD; +/* support for CitusNewNode() macro */ +CitusNode *newCitusNodeMacroHolder; /* exports for SQL callable functions */ PG_FUNCTION_INFO_V1(citus_extradata_container); diff --git a/src/backend/distributed/worker/worker_partition_protocol.c b/src/backend/distributed/worker/worker_partition_protocol.c index 834fa6763..c6a1d8fa9 100644 --- a/src/backend/distributed/worker/worker_partition_protocol.c +++ b/src/backend/distributed/worker/worker_partition_protocol.c @@ -73,6 +73,7 @@ static void OutputBinaryHeaders(FileOutputStream *partitionFileArray, uint32 fil static void OutputBinaryFooters(FileOutputStream *partitionFileArray, uint32 fileCount); static uint32 RangePartitionId(Datum partitionValue, const void *context); static uint32 HashPartitionId(Datum partitionValue, const void *context); +static bool FileIsLink(char *filename, struct stat filestat); /* exports for SQL callable functions */ @@ -614,6 +615,25 @@ CitusCreateDirectory(StringInfo directoryName) } +#ifdef WIN32 +static bool +FileIsLink(char *filename, struct stat filestat) +{ + return pgwin32_is_junction(filename); +} + + +#else +static bool +FileIsLink(char *filename, struct stat filestat) +{ + return S_ISLNK(filestat.st_mode); +} + + +#endif + + /* * CitusRemoveDirectory first checks if the given directory exists. If it does, the * function recursively deletes the contents of the given directory, and then @@ -645,7 +665,7 @@ CitusRemoveDirectory(StringInfo filename) * content, recurse into this function. Also, make sure that we do not * recurse into symbolic links. */ - if (S_ISDIR(fileStat.st_mode) && !S_ISLNK(fileStat.st_mode)) + if (S_ISDIR(fileStat.st_mode) && !FileIsLink(filename->data, fileStat)) { const char *directoryName = filename->data; struct dirent *directoryEntry = NULL; diff --git a/src/include/distributed/citus_nodes.h b/src/include/distributed/citus_nodes.h index b25082472..5a579e3aa 100644 --- a/src/include/distributed/citus_nodes.h +++ b/src/include/distributed/citus_nodes.h @@ -89,6 +89,11 @@ CitusNodeTagI(Node *node) return ((CitusNode*)(node))->citus_tag; } +/* + * Postgres's nodes/nodes.h has more information on why we do this. + */ +#ifdef __GNUC__ + /* Citus variant of newNode(), don't use directly. */ #define CitusNewNode(size, tag) \ ({ CitusNode *_result; \ @@ -100,6 +105,22 @@ CitusNodeTagI(Node *node) _result; \ }) +#else + +extern CitusNode *newCitusNodeMacroHolder; + +#define CitusNewNode(size, tag) \ +( \ + AssertMacro((size) >= sizeof(CitusNode)), /* need the tag, at least */ \ + newCitusNodeMacroHolder = (CitusNode *) palloc0fast(size), \ + newCitusNodeMacroHolder->extensible.type = T_ExtensibleNode, \ + newCitusNodeMacroHolder->extensible.extnodename = CitusNodeTagNames[tag - CITUS_NODE_TAG_START], \ + newCitusNodeMacroHolder->citus_tag =(int) (tag), \ + newCitusNodeMacroHolder \ +) + +#endif + /* * IsA equivalent that compares node tags, including Citus-specific nodes. diff --git a/src/include/distributed/errormessage.h b/src/include/distributed/errormessage.h index 26f8dd63a..ffc9ae0f0 100644 --- a/src/include/distributed/errormessage.h +++ b/src/include/distributed/errormessage.h @@ -11,6 +11,7 @@ #define ERRORMESSAGE_H +#include "c.h" #include "distributed/citus_nodes.h" @@ -34,7 +35,8 @@ typedef struct DeferredErrorMessage * serialized/copied/deserialized, i.e. can be embedded in plans and such. */ #define DeferredError(code, message, detail, hint) \ - DeferredErrorInternal(code, message, detail, hint, __FILE__, __LINE__, __func__) + DeferredErrorInternal(code, message, detail, hint, __FILE__, __LINE__, \ + PG_FUNCNAME_MACRO) DeferredErrorMessage * DeferredErrorInternal(int code, const char *message, const char *detail, const char *hint, @@ -48,12 +50,22 @@ DeferredErrorMessage * DeferredErrorInternal(int code, const char *message, cons * The trickery with __builtin_constant_p/pg_unreachable aims to have the * compiler understand that the function will not return if elevel >= ERROR. */ +#ifdef HAVE__BUILTIN_CONSTANT_P #define RaiseDeferredError(error, elevel) \ do { \ RaiseDeferredErrorInternal(error, elevel); \ if (__builtin_constant_p(elevel) && (elevel) >= ERROR) { \ pg_unreachable(); } \ } while (0) +#else /* !HAVE_BUILTIN_CONSTANT_P */ +#define RaiseDeferredError(error, elevel) \ + do { \ + const int elevel_ = (elevel); \ + RaiseDeferredErrorInternal(error, elevel_); \ + if (elevel_ >= ERROR) { \ + pg_unreachable(); } \ + } while (0) +#endif /* HAVE_BUILTIN_CONSTANT_P */ void RaiseDeferredErrorInternal(DeferredErrorMessage *error, int elevel);