From 8832f0f35896c16efd7de4cf35ef97348c90f2f6 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Fri, 29 Dec 2006 10:50:22 +0000 Subject: [PATCH] De-escape XML names when reverse-compiling XML expressions. --- src/backend/utils/adt/ruleutils.c | 12 ++---- src/backend/utils/adt/xml.c | 72 ++++++++++++++++++++++++++++++- src/include/utils/xml.h | 3 +- 3 files changed, 76 insertions(+), 11 deletions(-) diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 699b4a9370..136f1386cf 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -2,7 +2,7 @@ * ruleutils.c - Functions to convert stored expressions/querytrees * back to source text * - * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.238 2006/12/24 00:29:19 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.239 2006/12/29 10:50:22 petere Exp $ **********************************************************************/ #include "postgres.h" @@ -3810,11 +3810,8 @@ get_rule_expr(Node *node, deparse_context *context, } if (xexpr->name) { - /* - * XXX need to de-escape the name - */ appendStringInfo(buf, "NAME %s", - quote_identifier(xexpr->name)); + quote_identifier(map_xml_name_to_sql_identifier(xexpr->name))); needcomma = true; } if (xexpr->named_args) @@ -3834,11 +3831,8 @@ get_rule_expr(Node *node, deparse_context *context, if (needcomma) appendStringInfoString(buf, ", "); get_rule_expr((Node *) e, context, true); - /* - * XXX need to de-escape the name - */ appendStringInfo(buf, " AS %s", - quote_identifier(argname)); + quote_identifier(map_xml_name_to_sql_identifier(argname))); needcomma = true; } if (xexpr->op != IS_XMLFOREST) diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c index 6cde8d6aa4..6f4c87f824 100644 --- a/src/backend/utils/adt/xml.c +++ b/src/backend/utils/adt/xml.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.7 2006/12/28 14:28:36 petere Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.8 2006/12/29 10:50:22 petere Exp $ * *------------------------------------------------------------------------- */ @@ -882,6 +882,42 @@ sqlchar_to_unicode(char *s) } +static char * +unicode_to_sqlchar(pg_wchar c) +{ + char utf8string[4] = { '\0', '\0', '\0', '\0' }; + + if (c <= 0x7F) + { + utf8string[0] = c; + } + else if (c <= 0x7FF) + { + utf8string[0] = 0xC0 | ((c >> 6) & 0x1F); + utf8string[1] = 0x80 | (c & 0x3F); + } + else if (c <= 0xFFFF) + { + utf8string[0] = 0xE0 | ((c >> 12) & 0x0F); + utf8string[1] = 0x80 | ((c >> 6) & 0x3F); + utf8string[2] = 0x80 | (c & 0x3F); + } + else + { + utf8string[0] = 0xF0 | ((c >> 18) & 0x07); + utf8string[1] = 0x80 | ((c >> 12) & 0x3F); + utf8string[2] = 0x80 | ((c >> 6) & 0x3F); + utf8string[3] = 0x80 | (c & 0x3F); + + } + + return (char *) pg_do_encoding_conversion((unsigned char *) utf8string, + pg_mblen(utf8string), + PG_UTF8, + GetDatabaseEncoding()); +} + + static bool is_valid_xml_namefirst(pg_wchar c) { @@ -949,3 +985,37 @@ map_sql_identifier_to_xml_name(char *ident, bool fully_escaped) return NULL; #endif /* not USE_LIBXML */ } + + +/* + * The inverse; see SQL/XML:2003 section 9.17. + */ +char * +map_xml_name_to_sql_identifier(char *name) +{ + StringInfoData buf; + char *p; + + initStringInfo(&buf); + + for (p = name; *p; p += pg_mblen(p)) + { + if (*p == '_' && *(p+1) == 'x' + && isxdigit((unsigned char) *(p+2)) + && isxdigit((unsigned char) *(p+3)) + && isxdigit((unsigned char) *(p+4)) + && isxdigit((unsigned char) *(p+5)) + && *(p+6) == '_') + { + unsigned int u; + + sscanf(p + 2, "%X", &u); + appendStringInfoString(&buf, unicode_to_sqlchar(u)); + p += 6; + } + else + appendBinaryStringInfo(&buf, p, pg_mblen(p)); + } + + return buf.data; +} diff --git a/src/include/utils/xml.h b/src/include/utils/xml.h index ca50142032..20666a48cc 100644 --- a/src/include/utils/xml.h +++ b/src/include/utils/xml.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/xml.h,v 1.4 2006/12/28 14:28:36 petere Exp $ + * $PostgreSQL: pgsql/src/include/utils/xml.h,v 1.5 2006/12/29 10:50:22 petere Exp $ * *------------------------------------------------------------------------- */ @@ -37,5 +37,6 @@ extern xmltype *xmlpi(char *target, text *arg); extern xmltype *xmlroot(xmltype *data, text *version, int standalone); extern char *map_sql_identifier_to_xml_name(char *ident, bool fully_escaped); +extern char *map_xml_name_to_sql_identifier(char *name); #endif /* XML_H */