aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/nodes/outfuncs.c21
-rw-r--r--src/backend/nodes/readfuncs.c14
2 files changed, 30 insertions, 5 deletions
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index 24ea0487e7f..63dda75ae52 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -135,16 +135,23 @@ static void outChar(StringInfo str, char c);
* Convert an ordinary string (eg, an identifier) into a form that
* will be decoded back to a plain token by read.c's functions.
*
- * If a null or empty string is given, it is encoded as "<>".
+ * If a null string pointer is given, it is encoded as '<>'.
+ * An empty string is encoded as '""'. To avoid ambiguity, input
+ * strings beginning with '<' or '"' receive a leading backslash.
*/
void
outToken(StringInfo str, const char *s)
{
- if (s == NULL || *s == '\0')
+ if (s == NULL)
{
appendStringInfoString(str, "<>");
return;
}
+ if (*s == '\0')
+ {
+ appendStringInfoString(str, "\"\"");
+ return;
+ }
/*
* Look for characters or patterns that are treated specially by read.c
@@ -178,6 +185,13 @@ outChar(StringInfo str, char c)
{
char in[2];
+ /* Traditionally, we've represented \0 as <>, so keep doing that */
+ if (c == '\0')
+ {
+ appendStringInfoString(str, "<>");
+ return;
+ }
+
in[0] = c;
in[1] = '\0';
@@ -636,7 +650,8 @@ _outString(StringInfo str, const String *node)
{
/*
* We use outToken to provide escaping of the string's content, but we
- * don't want it to do anything with an empty string.
+ * don't want it to convert an empty string to '""', because we're putting
+ * double quotes around the string already.
*/
appendStringInfoChar(str, '"');
if (node->sval[0] != '\0')
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
index 89a9a50f7cb..b4ff855f7c6 100644
--- a/src/backend/nodes/readfuncs.c
+++ b/src/backend/nodes/readfuncs.c
@@ -178,8 +178,18 @@
#define strtobool(x) ((*(x) == 't') ? true : false)
-#define nullable_string(token,length) \
- ((length) == 0 ? NULL : debackslash(token, length))
+static char *
+nullable_string(const char *token, int length)
+{
+ /* outToken emits <> for NULL, and pg_strtok makes that an empty string */
+ if (length == 0)
+ return NULL;
+ /* outToken emits "" for empty string */
+ if (length == 2 && token[0] == '"' && token[1] == '"')
+ return pstrdup("");
+ /* otherwise, we must remove protective backslashes added by outToken */
+ return debackslash(token, length);
+}
/*