#include <ctype.h>
+#include "access/attnum.h"
#include "lib/stringinfo.h"
#include "miscadmin.h"
#include "nodes/bitmapset.h"
(appendStringInfoString(str, " :" CppAsString(fldname) " "), \
outBitmapset(str, node->fldname))
+/* Write a variable-length array of AttrNumber */
#define WRITE_ATTRNUMBER_ARRAY(fldname, len) \
- do { \
- appendStringInfoString(str, " :" CppAsString(fldname) " "); \
- for (int i = 0; i < len; i++) \
- appendStringInfo(str, " %d", node->fldname[i]); \
- } while(0)
+ (appendStringInfoString(str, " :" CppAsString(fldname) " "), \
+ writeAttrNumberCols(str, node->fldname, len))
+/* Write a variable-length array of Oid */
#define WRITE_OID_ARRAY(fldname, len) \
- do { \
- appendStringInfoString(str, " :" CppAsString(fldname) " "); \
- for (int i = 0; i < len; i++) \
- appendStringInfo(str, " %u", node->fldname[i]); \
- } while(0)
+ (appendStringInfoString(str, " :" CppAsString(fldname) " "), \
+ writeOidCols(str, node->fldname, len))
-/*
- * This macro supports the case that the field is NULL. For the other array
- * macros, that is currently not needed.
- */
+/* Write a variable-length array of Index */
#define WRITE_INDEX_ARRAY(fldname, len) \
- do { \
- appendStringInfoString(str, " :" CppAsString(fldname) " "); \
- if (node->fldname) \
- for (int i = 0; i < len; i++) \
- appendStringInfo(str, " %u", node->fldname[i]); \
- else \
- appendStringInfoString(str, "<>"); \
- } while(0)
+ (appendStringInfoString(str, " :" CppAsString(fldname) " "), \
+ writeIndexCols(str, node->fldname, len))
+/* Write a variable-length array of int */
#define WRITE_INT_ARRAY(fldname, len) \
- do { \
- appendStringInfoString(str, " :" CppAsString(fldname) " "); \
- for (int i = 0; i < len; i++) \
- appendStringInfo(str, " %d", node->fldname[i]); \
- } while(0)
+ (appendStringInfoString(str, " :" CppAsString(fldname) " "), \
+ writeIntCols(str, node->fldname, len))
+/* Write a variable-length array of bool */
#define WRITE_BOOL_ARRAY(fldname, len) \
- do { \
- appendStringInfoString(str, " :" CppAsString(fldname) " "); \
- for (int i = 0; i < len; i++) \
- appendStringInfo(str, " %s", booltostr(node->fldname[i])); \
- } while(0)
-
+ (appendStringInfoString(str, " :" CppAsString(fldname) " "), \
+ writeBoolCols(str, node->fldname, len))
#define booltostr(x) ((x) ? "true" : "false")
outToken(str, in);
}
+/*
+ * common implementation for scalar-array-writing functions
+ *
+ * The data format is either "<>" for a NULL pointer or "(item item item)".
+ * fmtstr must include a leading space, and the rest of it must produce
+ * something that will be seen as a single simple token by pg_strtok().
+ * convfunc can be empty, or the name of a conversion macro or function.
+ */
+#define WRITE_SCALAR_ARRAY(fnname, datatype, fmtstr, convfunc) \
+static void \
+fnname(StringInfo str, const datatype *arr, int len) \
+{ \
+ if (arr != NULL) \
+ { \
+ appendStringInfoChar(str, '('); \
+ for (int i = 0; i < len; i++) \
+ appendStringInfo(str, fmtstr, convfunc(arr[i])); \
+ appendStringInfoChar(str, ')'); \
+ } \
+ else \
+ appendStringInfoString(str, "<>"); \
+}
+
+WRITE_SCALAR_ARRAY(writeAttrNumberCols, AttrNumber, " %d",)
+WRITE_SCALAR_ARRAY(writeOidCols, Oid, " %u",)
+WRITE_SCALAR_ARRAY(writeIndexCols, Index, " %u",)
+WRITE_SCALAR_ARRAY(writeIntCols, int, " %d",)
+WRITE_SCALAR_ARRAY(writeBoolCols, bool, " %s", booltostr)
+
+/*
+ * Print a List.
+ */
static void
_outList(StringInfo str, const List *node)
{
}
/*
- * readAttrNumberCols
- */
-AttrNumber *
-readAttrNumberCols(int numCols)
-{
- int tokenLength,
- i;
- const char *token;
- AttrNumber *attr_vals;
-
- if (numCols <= 0)
- return NULL;
-
- attr_vals = (AttrNumber *) palloc(numCols * sizeof(AttrNumber));
- for (i = 0; i < numCols; i++)
- {
- token = pg_strtok(&tokenLength);
- attr_vals[i] = atoi(token);
- }
-
- return attr_vals;
-}
-
-/*
- * readOidCols
- */
-Oid *
-readOidCols(int numCols)
-{
- int tokenLength,
- i;
- const char *token;
- Oid *oid_vals;
-
- if (numCols <= 0)
- return NULL;
-
- oid_vals = (Oid *) palloc(numCols * sizeof(Oid));
- for (i = 0; i < numCols; i++)
- {
- token = pg_strtok(&tokenLength);
- oid_vals[i] = atooid(token);
- }
-
- return oid_vals;
-}
-
-/*
- * readIntCols
+ * common implementation for scalar-array-reading functions
+ *
+ * The data format is either "<>" for a NULL pointer (in which case numCols
+ * is ignored) or "(item item item)" where the number of items must equal
+ * numCols. The convfunc must be okay with stopping at whitespace or a
+ * right parenthesis, since pg_strtok won't null-terminate the token.
*/
-int *
-readIntCols(int numCols)
-{
- int tokenLength,
- i;
- const char *token;
- int *int_vals;
-
- if (numCols <= 0)
- return NULL;
-
- int_vals = (int *) palloc(numCols * sizeof(int));
- for (i = 0; i < numCols; i++)
- {
- token = pg_strtok(&tokenLength);
- int_vals[i] = atoi(token);
- }
-
- return int_vals;
+#define READ_SCALAR_ARRAY(fnname, datatype, convfunc) \
+datatype * \
+fnname(int numCols) \
+{ \
+ datatype *vals; \
+ READ_TEMP_LOCALS(); \
+ token = pg_strtok(&length); \
+ if (token == NULL) \
+ elog(ERROR, "incomplete scalar array"); \
+ if (length == 0) \
+ return NULL; /* it was "<>", so return NULL pointer */ \
+ if (length != 1 || token[0] != '(') \
+ elog(ERROR, "unrecognized token: \"%.*s\"", length, token); \
+ vals = (datatype *) palloc(numCols * sizeof(datatype)); \
+ for (int i = 0; i < numCols; i++) \
+ { \
+ token = pg_strtok(&length); \
+ if (token == NULL || token[0] == ')') \
+ elog(ERROR, "incomplete scalar array"); \
+ vals[i] = convfunc(token); \
+ } \
+ token = pg_strtok(&length); \
+ if (token == NULL || length != 1 || token[0] != ')') \
+ elog(ERROR, "incomplete scalar array"); \
+ return vals; \
}
/*
- * readBoolCols
+ * Note: these functions are exported in nodes.h for possible use by
+ * extensions, so don't mess too much with their names or API.
*/
-bool *
-readBoolCols(int numCols)
-{
- int tokenLength,
- i;
- const char *token;
- bool *bool_vals;
-
- if (numCols <= 0)
- return NULL;
-
- bool_vals = (bool *) palloc(numCols * sizeof(bool));
- for (i = 0; i < numCols; i++)
- {
- token = pg_strtok(&tokenLength);
- bool_vals[i] = strtobool(token);
- }
-
- return bool_vals;
-}
+READ_SCALAR_ARRAY(readAttrNumberCols, int16, atoi)
+READ_SCALAR_ARRAY(readOidCols, Oid, atooid)
+/* outfuncs.c has writeIndexCols, but we don't yet need that here */
+/* READ_SCALAR_ARRAY(readIndexCols, Index, atoui) */
+READ_SCALAR_ARRAY(readIntCols, int, atoi)
+READ_SCALAR_ARRAY(readBoolCols, bool, strtobool)