On 6/18/17 10:14, Tom Lane wrote:
> pg_strtok recognizes "<>" and returns length = 0, so debackslash()
> would produce the right answer AFAICS (admittedly, I haven't tested).
> But I don't really want to do it like that because of the wasted
> palloc space and cycles.
> 
>> Maybe
>> local_node->fldname = length ? token[0] : '\0';
>> ?
> 
> Doesn't cope with backslash-quoted characters.  If we're going to bother
> to do anything here, I think we ought to make it reversible for all
> possible characters.

Makes sense.  Updated patch attached.

-- 
Peter Eisentraut              http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
From 3b221dc64e1e9eb74b48a97fba4bfa18fad4bf4a Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pete...@gmx.net>
Date: Wed, 21 Jun 2017 22:57:23 -0400
Subject: [PATCH v2] Fix output of char node fields

WRITE_CHAR_FIELD() didn't do any escaping, so that for example a zero
byte would cause the whole output string to be truncated.  To fix, pass
the char through outToken(), so it is escaped like a string.  Adjust the
reading side to handle this.
---
 src/backend/nodes/outfuncs.c  | 20 +++++++++++++++++++-
 src/backend/nodes/readfuncs.c |  3 ++-
 2 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index 3a23f0bb16..b0abe9ec10 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -32,6 +32,8 @@
 #include "utils/datum.h"
 #include "utils/rel.h"
 
+static void outChar(StringInfo str, char c);
+
 
 /*
  * Macros to simplify output of different kinds of fields.  Use these
@@ -62,7 +64,8 @@
 
 /* Write a char field (ie, one ascii character) */
 #define WRITE_CHAR_FIELD(fldname) \
-       appendStringInfo(str, " :" CppAsString(fldname) " %c", node->fldname)
+       (appendStringInfo(str, " :" CppAsString(fldname) " "), \
+        outChar(str, node->fldname))
 
 /* Write an enumerated-type field as an integer code */
 #define WRITE_ENUM_FIELD(fldname, enumtype) \
@@ -140,6 +143,21 @@ outToken(StringInfo str, const char *s)
        }
 }
 
+/*
+ * Convert one char.  Goes through outToken() so that special characters are
+ * escaped.
+ */
+static void
+outChar(StringInfo str, char c)
+{
+       char            in[2];
+
+       in[0] = c;
+       in[1] = '\0';
+
+       outToken(str, in);
+}
+
 static void
 _outList(StringInfo str, const List *node)
 {
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
index 2988e8bd16..1380703cbc 100644
--- a/src/backend/nodes/readfuncs.c
+++ b/src/backend/nodes/readfuncs.c
@@ -86,7 +86,8 @@
 #define READ_CHAR_FIELD(fldname) \
        token = pg_strtok(&length);             /* skip :fldname */ \
        token = pg_strtok(&length);             /* get field value */ \
-       local_node->fldname = token[0]
+       /* avoid overhead of calling debackslash() for one char */ \
+       local_node->fldname = (length == 0) ? '\0' : (token[0] == '\\' ? 
token[1] : token[0])
 
 /* Read an enumerated-type field that was written as an integer code */
 #define READ_ENUM_FIELD(fldname, enumtype) \
-- 
2.13.1

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to