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