49 #include <libxml/chvalid.h>
50 #include <libxml/parser.h>
51 #include <libxml/parserInternals.h>
52 #include <libxml/tree.h>
53 #include <libxml/uri.h>
54 #include <libxml/xmlerror.h>
55 #include <libxml/xmlversion.h>
56 #include <libxml/xmlwriter.h>
57 #include <libxml/xpath.h>
58 #include <libxml/xpathInternals.h>
65 #if LIBXML_VERSION >= 20704
66 #define HAVE_XMLSTRUCTUREDERRORCONTEXT 1
101 #define ERRCXT_MAGIC 68275028
112 xmlStructuredErrorFunc saved_errfunc;
115 xmlExternalEntityLoader saved_entityfunc;
118 static xmlParserInputPtr xmlPgEntityLoader(
const char *URL,
const char *ID,
119 xmlParserCtxtPtr ctxt);
120 static void xml_errorHandler(
void *data, xmlErrorPtr
error);
121 static void xml_ereport_by_code(
int level,
int sqlcode,
123 static void chopStringInfoNewlines(
StringInfo str);
124 static void appendStringInfoLineSeparator(
StringInfo str);
126 #ifdef USE_LIBXMLCONTEXT
130 static void xml_memory_init(
void);
131 static void *xml_palloc(
size_t size);
132 static void *xml_repalloc(
void *ptr,
size_t size);
133 static void xml_pfree(
void *ptr);
134 static char *xml_pstrdup(
const char *
string);
137 static xmlChar *xml_text2xmlChar(
text *in);
138 static int parse_xml_decl(
const xmlChar *str,
size_t *lenp,
139 xmlChar **version, xmlChar **
encoding,
int *standalone);
140 static bool print_xml_decl(
StringInfo buf,
const xmlChar *version,
143 bool preserve_whitespace,
int encoding);
144 static text *xml_xmlnodetoxmltype(xmlNodePtr
cur);
145 static int xml_xpathobjtoxmlarray(xmlXPathObjectPtr xpathobj,
150 const char *xmlschema,
bool nulls,
bool tableforest,
151 const char *targetns,
bool top_level);
153 bool nulls,
bool tableforest,
const char *targetns);
155 List *relid_list,
bool nulls,
156 bool tableforest,
const char *targetns);
158 bool nulls,
bool tableforest,
159 const char *targetns);
164 char *tablename,
bool nulls,
bool tableforest,
165 const char *targetns,
bool top_level);
167 #define NO_XML_SUPPORT() \
169 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), \
170 errmsg("unsupported XML feature"), \
171 errdetail("This functionality requires the server to be built with libxml support."), \
172 errhint("You need to rebuild PostgreSQL using --with-libxml.")))
176 #define NAMESPACE_XSD "http://www.w3.org/2001/XMLSchema"
177 #define NAMESPACE_XSI "http://www.w3.org/2001/XMLSchema-instance"
178 #define NAMESPACE_SQLXML "http://standards.iso.org/iso/9075/2003/sqlxml"
184 xmlChar_to_encoding(
const xmlChar *encoding_name)
190 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
191 errmsg(
"invalid encoding name \"%s\"",
192 (
const char *) encoding_name)));
230 #define PG_XML_DEFAULT_VERSION "1.0"
246 size_t len = strlen(str);
251 if ((res_code = parse_xml_decl((xmlChar *) str,
252 &len, &version,
NULL, &standalone)) == 0)
258 if (!print_xml_decl(&buf, version, target_encoding, standalone))
265 if (*(str + len) ==
'\n')
275 xml_ereport_by_code(
WARNING, ERRCODE_INTERNAL_ERROR,
276 "could not parse XML declaration in stored value",
308 xmlChar *encodingStr =
NULL;
326 memcpy(
VARDATA(result), str, nbytes);
330 parse_xml_decl((
const xmlChar *) str,
NULL,
NULL, &encodingStr,
NULL);
338 encoding = encodingStr ? xmlChar_to_encoding(encodingStr) :
PG_UTF8;
344 doc = xml_parse(result,
xmloption,
true, encoding);
410 xmlBuffer_to_xmltype(xmlBufferPtr
buf)
413 xmlBufferLength(buf));
429 for (i = 1; i < len; i++)
431 if (argdata[i] ==
'-' && argdata[i - 1] ==
'-')
433 (
errcode(ERRCODE_INVALID_XML_COMMENT),
434 errmsg(
"invalid XML comment")));
436 if (len > 0 && argdata[len - 1] ==
'-')
438 (
errcode(ERRCODE_INVALID_XML_COMMENT),
439 errmsg(
"invalid XML comment")));
463 int global_standalone = 1;
464 xmlChar *global_version =
NULL;
465 bool global_version_no_value =
false;
481 parse_xml_decl((xmlChar *) str, &len, &version,
NULL, &standalone);
483 if (standalone == 0 && global_standalone == 1)
484 global_standalone = 0;
486 global_standalone = -1;
489 global_version_no_value =
true;
490 else if (!global_version)
491 global_version = version;
492 else if (xmlStrcmp(version, global_version) != 0)
493 global_version_no_value =
true;
499 if (!global_version_no_value || global_standalone >= 0)
505 print_xml_decl(&buf2,
506 (!global_version_no_value) ? global_version :
NULL,
567 (
errcode(ERRCODE_NOT_AN_XML_DOCUMENT),
568 errmsg(
"not an XML document")));
571 return (
text *) data;
581 List *named_arg_strings;
587 volatile xmlBufferPtr buf =
NULL;
588 volatile xmlTextWriterPtr writer =
NULL;
596 named_arg_strings =
NIL;
610 named_arg_strings =
lappend(named_arg_strings, str);
628 arg_strings =
lappend(arg_strings, str);
637 buf = xmlBufferCreate();
638 if (buf ==
NULL || xmlerrcxt->err_occurred)
640 "could not allocate xmlBuffer");
641 writer = xmlNewTextWriterMemory(buf, 0);
642 if (writer ==
NULL || xmlerrcxt->err_occurred)
644 "could not allocate xmlTextWriter");
646 xmlTextWriterStartElement(writer, (xmlChar *) xexpr->
name);
654 xmlTextWriterWriteAttribute(writer,
659 foreach(
arg, arg_strings)
663 xmlTextWriterWriteRaw(writer, (xmlChar *) str);
666 xmlTextWriterEndElement(writer);
669 xmlFreeTextWriter(writer);
672 result = xmlBuffer_to_xmltype(buf);
677 xmlFreeTextWriter(writer);
705 doc = xml_parse(data, xmloption_arg, preserve_whitespace,
726 (
errcode(ERRCODE_SYNTAX_ERROR),
727 errmsg(
"invalid XML processing instruction"),
728 errdetail(
"XML processing instruction target name cannot be \"%s\".", target)));
734 *result_is_null = arg_is_null;
747 if (strstr(
string,
"?>") !=
NULL)
749 (
errcode(ERRCODE_INVALID_XML_PROCESSING_INSTRUCTION),
750 errmsg(
"invalid XML processing instruction"),
751 errdetail(
"XML processing instruction cannot contain \"?>\".")));
775 xmlChar *orig_version;
782 parse_xml_decl((xmlChar *) str, &len, &orig_version,
NULL, &orig_standalone);
785 orig_version = xml_text2xmlChar(version);
798 orig_standalone = -1;
806 print_xml_decl(&buf, orig_version, 0, orig_standalone);
829 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
830 errmsg(
"xmlvalidate is not implemented")));
840 volatile xmlDocPtr doc =
NULL;
857 if (errdata->
sqlerrcode == ERRCODE_INVALID_XML_DOCUMENT)
897 static bool first_time =
true;
907 if (
sizeof(
char) !=
sizeof(xmlChar))
909 (
errmsg(
"could not initialize XML library"),
910 errdetail(
"libxml2 has incompatible char type: sizeof(char)=%u, sizeof(xmlChar)=%u.",
911 (
int)
sizeof(
char), (
int)
sizeof(xmlChar))));
913 #ifdef USE_LIBXMLCONTEXT
951 errcxt->magic = ERRCXT_MAGIC;
952 errcxt->strictness = strictness;
953 errcxt->err_occurred =
false;
963 errcxt->saved_errfunc = xmlStructuredError;
965 #ifdef HAVE_XMLSTRUCTUREDERRORCONTEXT
966 errcxt->saved_errcxt = xmlStructuredErrorContext;
968 errcxt->saved_errcxt = xmlGenericErrorContext;
971 xmlSetStructuredErrorFunc((
void *) errcxt, xml_errorHandler);
987 #ifdef HAVE_XMLSTRUCTUREDERRORCONTEXT
988 new_errcxt = xmlStructuredErrorContext;
990 new_errcxt = xmlGenericErrorContext;
993 if (new_errcxt != (
void *) errcxt)
995 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
996 errmsg(
"could not set up XML error handler"),
997 errhint(
"This probably indicates that the version of libxml2"
998 " being used is not compatible with the libxml2"
999 " header files that PostgreSQL was built with.")));
1005 errcxt->saved_entityfunc = xmlGetExternalEntityLoader();
1006 xmlSetExternalEntityLoader(xmlPgEntityLoader);
1027 Assert(errcxt->magic == ERRCXT_MAGIC);
1034 Assert(!errcxt->err_occurred || isError);
1041 #ifdef HAVE_XMLSTRUCTUREDERRORCONTEXT
1042 cur_errcxt = xmlStructuredErrorContext;
1044 cur_errcxt = xmlGenericErrorContext;
1047 if (cur_errcxt != (
void *) errcxt)
1048 elog(
WARNING,
"libxml error handling state is out of sync with xml.c");
1051 xmlSetStructuredErrorFunc(errcxt->saved_errcxt, errcxt->saved_errfunc);
1052 xmlSetExternalEntityLoader(errcxt->saved_entityfunc);
1061 pfree(errcxt->err_buf.data);
1072 return errcxt->err_occurred;
1085 #define CHECK_XML_SPACE(p) \
1087 if (!xmlIsBlank_ch(*(p))) \
1088 return XML_ERR_SPACE_REQUIRED; \
1091 #define SKIP_XML_SPACE(p) \
1092 while (xmlIsBlank_ch(*(p))) (p)++
1096 #define PG_XMLISNAMECHAR(c) \
1097 (xmlIsBaseChar_ch(c) || xmlIsIdeographicQ(c) \
1098 || xmlIsDigit_ch(c) \
1099 || c == '.' || c == '-' || c == '_' || c == ':' \
1100 || xmlIsCombiningQ(c) \
1101 || xmlIsExtender_ch(c))
1105 xml_pnstrdup(
const xmlChar *str,
size_t len)
1109 result = (xmlChar *)
palloc((len + 1) *
sizeof(xmlChar));
1110 memcpy(result, str, len *
sizeof(xmlChar));
1122 parse_xml_decl(
const xmlChar *str,
size_t *lenp,
1123 xmlChar **version, xmlChar **
encoding,
int *standalone)
1126 const xmlChar *save_p;
1149 if (xmlStrncmp(p, (xmlChar *)
"<?xml", 5) != 0)
1153 utf8len = strlen((
const char *) (p + 5));
1154 utf8char = xmlGetUTF8Char(p + 5, &utf8len);
1155 if (PG_XMLISNAMECHAR(utf8char))
1163 if (xmlStrncmp(p, (xmlChar *)
"version", 7) != 0)
1164 return XML_ERR_VERSION_MISSING;
1168 return XML_ERR_VERSION_MISSING;
1172 if (*p ==
'\'' || *p ==
'"')
1176 q = xmlStrchr(p + 1, *p);
1178 return XML_ERR_VERSION_MISSING;
1181 *version = xml_pnstrdup(p + 1, q - p - 1);
1185 return XML_ERR_VERSION_MISSING;
1190 if (xmlStrncmp(p, (xmlChar *)
"encoding", 8) == 0)
1192 CHECK_XML_SPACE(save_p);
1196 return XML_ERR_MISSING_ENCODING;
1200 if (*p ==
'\'' || *p ==
'"')
1204 q = xmlStrchr(p + 1, *p);
1206 return XML_ERR_MISSING_ENCODING;
1209 *encoding = xml_pnstrdup(p + 1, q - p - 1);
1213 return XML_ERR_MISSING_ENCODING;
1223 if (xmlStrncmp(p, (xmlChar *)
"standalone", 10) == 0)
1225 CHECK_XML_SPACE(save_p);
1229 return XML_ERR_STANDALONE_VALUE;
1232 if (xmlStrncmp(p, (xmlChar *)
"'yes'", 5) == 0 ||
1233 xmlStrncmp(p, (xmlChar *)
"\"yes\"", 5) == 0)
1239 else if (xmlStrncmp(p, (xmlChar *)
"'no'", 4) == 0 ||
1240 xmlStrncmp(p, (xmlChar *)
"\"no\"", 4) == 0)
1247 return XML_ERR_STANDALONE_VALUE;
1255 if (xmlStrncmp(p, (xmlChar *)
"?>", 2) != 0)
1256 return XML_ERR_XMLDECL_NOT_FINISHED;
1262 for (p = str; p < str + len; p++)
1264 return XML_ERR_INVALID_CHAR;
1288 print_xml_decl(
StringInfo buf,
const xmlChar *version,
1289 pg_enc encoding,
int standalone)
1292 || (encoding && encoding !=
PG_UTF8)
1293 || standalone != -1)
1302 if (encoding && encoding !=
PG_UTF8)
1312 if (standalone == 1)
1314 else if (standalone == 0)
1340 xmlChar *utf8string;
1342 volatile xmlParserCtxtPtr ctxt =
NULL;
1343 volatile xmlDocPtr doc =
NULL;
1346 string = xml_text2xmlChar(data);
1361 ctxt = xmlNewParserCtxt();
1362 if (ctxt ==
NULL || xmlerrcxt->err_occurred)
1364 "could not allocate parser context");
1375 doc = xmlCtxtReadDoc(ctxt, utf8string,
1378 XML_PARSE_NOENT | XML_PARSE_DTDATTR
1379 | (preserve_whitespace ? 0 : XML_PARSE_NOBLANKS));
1380 if (doc ==
NULL || xmlerrcxt->err_occurred)
1382 "invalid XML document");
1391 res_code = parse_xml_decl(utf8string,
1392 &count, &version,
NULL, &standalone);
1394 xml_ereport_by_code(
ERROR, ERRCODE_INVALID_XML_CONTENT,
1395 "invalid XML content: invalid XML declaration",
1398 doc = xmlNewDoc(version);
1400 doc->encoding = xmlStrdup((
const xmlChar *)
"UTF-8");
1401 doc->standalone = standalone;
1404 if (*(utf8string + count))
1406 res_code = xmlParseBalancedChunkMemory(doc,
NULL,
NULL, 0,
1407 utf8string + count,
NULL);
1408 if (res_code != 0 || xmlerrcxt->err_occurred)
1410 "invalid XML content");
1419 xmlFreeParserCtxt(ctxt);
1427 xmlFreeParserCtxt(ctxt);
1439 xml_text2xmlChar(
text *in)
1445 #ifdef USE_LIBXMLCONTEXT
1452 xml_memory_init(
void)
1455 if (LibxmlContext ==
NULL)
1463 xmlMemSetup(xml_pfree, xml_palloc, xml_repalloc, xml_pstrdup);
1470 xml_palloc(
size_t size)
1477 xml_repalloc(
void *ptr,
size_t size)
1484 xml_pfree(
void *ptr)
1493 xml_pstrdup(
const char *
string)
1511 static xmlParserInputPtr
1512 xmlPgEntityLoader(
const char *URL,
const char *ID,
1513 xmlParserCtxtPtr ctxt)
1515 return xmlNewStringInputStream(ctxt, (
const xmlChar *)
"");
1535 if (errcxt->magic != ERRCXT_MAGIC)
1536 elog(
ERROR,
"xml_ereport called with invalid PgXmlErrorContext");
1539 errcxt->err_occurred =
false;
1542 if (errcxt->err_buf.len > 0)
1543 detail = errcxt->err_buf.data;
1558 xml_errorHandler(
void *data, xmlErrorPtr
error)
1561 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) error->ctxt;
1562 xmlParserInputPtr input = (ctxt !=
NULL) ? ctxt->input :
NULL;
1563 xmlNodePtr node = error->node;
1564 const xmlChar *
name = (node !=
NULL &&
1565 node->type == XML_ELEMENT_NODE) ? node->name :
NULL;
1566 int domain = error->domain;
1567 int level = error->level;
1576 if (xmlerrcxt->magic != ERRCXT_MAGIC)
1577 elog(
FATAL,
"xml_errorHandler called with invalid PgXmlErrorContext");
1587 switch (error->code)
1589 case XML_WAR_NS_URI:
1590 level = XML_ERR_ERROR;
1591 domain = XML_FROM_NAMESPACE;
1594 case XML_ERR_NS_DECL_ERROR:
1595 case XML_WAR_NS_URI_RELATIVE:
1596 case XML_WAR_NS_COLUMN:
1597 case XML_NS_ERR_XML_NAMESPACE:
1598 case XML_NS_ERR_UNDEFINED_NAMESPACE:
1599 case XML_NS_ERR_QNAME:
1600 case XML_NS_ERR_ATTRIBUTE_REDEFINED:
1601 case XML_NS_ERR_EMPTY:
1602 domain = XML_FROM_NAMESPACE;
1609 case XML_FROM_PARSER:
1611 case XML_FROM_MEMORY:
1618 if (error->code == XML_WAR_UNDECLARED_ENTITY)
1634 if (error->line > 0)
1653 xmlGenericErrorFunc errFuncSaved = xmlGenericError;
1654 void *errCtxSaved = xmlGenericErrorContext;
1656 xmlSetGenericErrorFunc((
void *) errorBuf,
1660 appendStringInfoLineSeparator(errorBuf);
1662 xmlParserPrintFileContext(input);
1665 xmlSetGenericErrorFunc(errCtxSaved, errFuncSaved);
1669 chopStringInfoNewlines(errorBuf);
1681 appendStringInfoLineSeparator(&xmlerrcxt->err_buf);
1684 pfree(errorBuf->data);
1697 if (level >= XML_ERR_ERROR)
1699 appendStringInfoLineSeparator(&xmlerrcxt->err_buf);
1702 xmlerrcxt->err_occurred =
true;
1704 else if (level >= XML_ERR_WARNING)
1715 pfree(errorBuf->data);
1728 xml_ereport_by_code(
int level,
int sqlcode,
1729 const char *msg,
int code)
1735 case XML_ERR_INVALID_CHAR:
1738 case XML_ERR_SPACE_REQUIRED:
1741 case XML_ERR_STANDALONE_VALUE:
1742 det =
gettext_noop(
"standalone accepts only 'yes' or 'no'.");
1744 case XML_ERR_VERSION_MISSING:
1745 det =
gettext_noop(
"Malformed declaration: missing version.");
1747 case XML_ERR_MISSING_ENCODING:
1748 det =
gettext_noop(
"Missing encoding in text declaration.");
1750 case XML_ERR_XMLDECL_NOT_FINISHED:
1751 det =
gettext_noop(
"Parsing XML declaration: '?>' expected.");
1754 det =
gettext_noop(
"Unrecognized libxml error code: %d.");
1771 while (str->
len > 0 && str->
data[str->
len - 1] ==
'\n')
1780 appendStringInfoLineSeparator(
StringInfo str)
1782 chopStringInfoNewlines(str);
1792 sqlchar_to_unicode(
char *s)
1803 if (utf8string != s)
1814 return (xmlIsBaseCharQ(c) || xmlIsIdeographicQ(c)
1815 || c ==
'_' || c ==
':');
1823 return (xmlIsBaseCharQ(c) || xmlIsIdeographicQ(c)
1825 || c ==
'.' || c ==
'-' || c ==
'_' || c ==
':'
1826 || xmlIsCombiningQ(c)
1827 || xmlIsExtenderQ(c));
1847 Assert(fully_escaped || !escape_period);
1851 for (p = ident; *p; p +=
pg_mblen(p))
1853 if (*p ==
':' && (p == ident || fully_escaped))
1855 else if (*p ==
'_' && *(p + 1) ==
'x')
1857 else if (fully_escaped && p == ident &&
1865 else if (escape_period && *p ==
'.')
1869 pg_wchar u = sqlchar_to_unicode(p);
1872 ? !is_valid_xml_namefirst(u)
1873 : !is_valid_xml_namechar(u))
1897 memset(utf8string, 0,
sizeof(utf8string));
1902 if (result == utf8string)
1919 for (p = name; *p; p +=
pg_mblen(p))
1921 if (*p ==
'_' && *(p + 1) ==
'x'
1922 && isxdigit((
unsigned char) *(p + 2))
1923 && isxdigit((
unsigned char) *(p + 3))
1924 && isxdigit((
unsigned char) *(p + 4))
1925 && isxdigit((
unsigned char) *(p + 5))
1930 sscanf(p + 2,
"%X", &u);
1972 elmlen, elmbyval, elmalign,
1973 &elem_values, &elem_nulls,
1978 for (i = 0; i < num_elems; i++)
2027 (
errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2028 errmsg(
"date out of range"),
2029 errdetail(
"XML does not support infinite date values.")));
2049 (
errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2050 errmsg(
"timestamp out of range"),
2051 errdetail(
"XML does not support infinite timestamp values.")));
2056 (
errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2057 errmsg(
"timestamp out of range")));
2068 const char *tzn =
NULL;
2076 (
errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2077 errmsg(
"timestamp out of range"),
2078 errdetail(
"XML does not support infinite timestamp values.")));
2083 (
errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2084 errmsg(
"timestamp out of range")));
2094 volatile xmlBufferPtr buf =
NULL;
2095 volatile xmlTextWriterPtr writer =
NULL;
2102 buf = xmlBufferCreate();
2103 if (buf ==
NULL || xmlerrcxt->err_occurred)
2105 "could not allocate xmlBuffer");
2106 writer = xmlNewTextWriterMemory(buf, 0);
2107 if (writer ==
NULL || xmlerrcxt->err_occurred)
2109 "could not allocate xmlTextWriter");
2112 xmlTextWriterWriteBase64(writer,
VARDATA_ANY(bstr),
2115 xmlTextWriterWriteBinHex(writer,
VARDATA_ANY(bstr),
2119 xmlFreeTextWriter(writer);
2122 result =
pstrdup((
const char *) xmlBufferContent(buf));
2127 xmlFreeTextWriter(writer);
2154 if (type ==
XMLOID || !xml_escape_strings)
2177 for (p = str; *p; p++)
2205 size_t len = strlen(s) + 1;
2208 memcpy(ret, s, len);
2290 appendStringInfo(&query,
"SELECT oid FROM pg_catalog.pg_class WHERE relnamespace = %u AND relkind IN ('r', 'm', 'v') AND pg_catalog.has_table_privilege (oid, 'SELECT') ORDER BY relname;", nspid);
2300 #define XML_VISIBLE_SCHEMAS_EXCLUDE "(nspname ~ '^pg_' OR nspname = 'information_schema')"
2302 #define XML_VISIBLE_SCHEMAS "SELECT oid FROM pg_catalog.pg_namespace WHERE pg_catalog.has_schema_privilege (oid, 'USAGE') AND NOT " XML_VISIBLE_SCHEMAS_EXCLUDE
2316 return query_to_oid_list(
"SELECT oid FROM pg_catalog.pg_class WHERE relkind IN ('r', 'm', 'v') AND pg_catalog.has_table_privilege (pg_class.oid, 'SELECT') AND relnamespace IN (" XML_VISIBLE_SCHEMAS ");");
2327 const char *xmlschema,
bool nulls,
bool tableforest,
2328 const char *targetns,
bool top_level)
2337 xmlschema, nulls, tableforest,
2338 targetns, top_level);
2365 NULL, nulls, tableforest,
2389 (
errcode(ERRCODE_UNDEFINED_CURSOR),
2390 errmsg(
"cursor \"%s\" does not exist", name)));
2395 tableforest, targetns,
true);
2417 const char *xmlschema,
const char *targetns,
2421 Assert(top_level || !xmlschema);
2427 if (strlen(targetns) > 0)
2433 if (strlen(targetns) > 0)
2451 const char *xmlschema,
bool nulls,
bool tableforest,
2452 const char *targetns,
bool top_level)
2468 (
errcode(ERRCODE_DATA_EXCEPTION),
2469 errmsg(
"invalid query")));
2474 targetns, top_level);
2483 tableforest, targetns, top_level);
2506 tableforest, targetns);
2527 elog(
ERROR,
"SPI_prepare(\"%s\") failed", query);
2530 elog(
ERROR,
"SPI_cursor_open(\"%s\") failed", query);
2534 tableforest, targetns));
2549 const char *xmlschema;
2556 (
errcode(ERRCODE_UNDEFINED_CURSOR),
2557 errmsg(
"cursor \"%s\" does not exist", name)));
2561 tableforest, targetns));
2576 const char *xmlschema;
2580 tableforest, targetns);
2584 xmlschema, nulls, tableforest,
2597 const char *xmlschema;
2604 elog(
ERROR,
"SPI_prepare(\"%s\") failed", query);
2607 elog(
ERROR,
"SPI_cursor_open(\"%s\") failed", query);
2615 xmlschema, nulls, tableforest,
2627 bool tableforest,
const char *targetns,
bool top_level)
2650 foreach(cell, relid_list)
2686 nulls, tableforest, targetns,
true)));
2699 if (strlen(targetns) > 0)
2702 " targetNamespace=\"%s\"\n"
2703 " elementFormDefault=\"qualified\"",
2719 bool tableforest,
const char *targetns)
2738 foreach(cell, relid_list)
2752 nulls, tableforest, targetns));
2771 nulls, tableforest, targetns)));
2790 tableforest, targetns);
2793 xmlschema->
data, nulls,
2794 tableforest, targetns,
true)));
2805 bool tableforest,
const char *targetns)
2828 foreach(cell, nspid_list)
2834 tableforest, targetns,
false);
2857 tableforest, targetns)));
2863 const char *targetns)
2881 foreach(cell, relid_list)
2912 tableforest, targetns)));
2927 nulls, tableforest, targetns)));
2968 bool tableforest,
const char *targetns)
2972 char *tabletypename;
2985 elog(
ERROR,
"cache lookup failed for relation %u", relid);
3010 tabletypename =
"TableType";
3011 rowtypename =
"RowType";
3020 "<xsd:complexType name=\"%s\">\n"
3021 " <xsd:sequence>\n",
3024 for (i = 0; i < tupdesc->
natts; i++)
3026 if (tupdesc->
attrs[i]->attisdropped)
3029 " <xsd:element name=\"%s\" type=\"%s\"%s></xsd:element>\n",
3033 nulls ?
" nillable=\"true\"" :
" minOccurs=\"0\"");
3037 " </xsd:sequence>\n"
3038 "</xsd:complexType>\n\n");
3043 "<xsd:complexType name=\"%s\">\n"
3045 " <xsd:element name=\"row\" type=\"%s\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n"
3046 " </xsd:sequence>\n"
3047 "</xsd:complexType>\n\n",
3048 tabletypename, rowtypename);
3051 "<xsd:element name=\"%s\" type=\"%s\"/>\n\n",
3052 xmltn, tabletypename);
3056 "<xsd:element name=\"%s\" type=\"%s\"/>\n\n",
3057 xmltn, rowtypename);
3071 bool tableforest,
const char *targetns)
3076 char *schematypename;
3093 "<xsd:complexType name=\"%s\">\n", schematypename);
3099 " <xsd:sequence>\n");
3101 foreach(cell, relid_list)
3113 " <xsd:element name=\"%s\" type=\"%s\"/>\n",
3114 xmltn, tabletypename);
3117 " <xsd:element name=\"%s\" type=\"%s\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n",
3118 xmltn, tabletypename);
3126 " </xsd:sequence>\n");
3128 "</xsd:complexType>\n\n");
3131 "<xsd:element name=\"%s\" type=\"%s\"/>\n\n",
3132 xmlsn, schematypename);
3144 bool tableforest,
const char *targetns)
3148 char *catalogtypename;
3164 "<xsd:complexType name=\"%s\">\n", catalogtypename);
3168 foreach(cell, nspid_list)
3179 " <xsd:element name=\"%s\" type=\"%s\"/>\n",
3180 xmlsn, schematypename);
3186 "</xsd:complexType>\n\n");
3189 "<xsd:element name=\"%s\" type=\"%s\"/>\n\n",
3190 xmlcn, catalogtypename);
3225 ((typmod -
VARHDRSZ) >> 16) & 0xffff,
3283 elog(
ERROR,
"cache lookup failed for type %u", typeoid);
3313 foreach(cell0, tupdesc_list)
3317 for (i = 0; i < tupdesc->
natts; i++)
3319 if (tupdesc->
attrs[i]->attisdropped)
3322 tupdesc->
attrs[i]->atttypid);
3327 foreach(cell0, uniquetypes)
3332 if (basetypid != typid)
3339 foreach(cell0, uniquetypes)
3369 "<xsd:complexType mixed=\"true\">\n"
3371 " <xsd:any name=\"element\" minOccurs=\"0\" maxOccurs=\"unbounded\" processContents=\"skip\"/>\n"
3372 " </xsd:sequence>\n"
3373 "</xsd:complexType>\n");
3378 "<xsd:simpleType name=\"%s\">\n",
typename);
3386 " <xsd:restriction base=\"xsd:string\">\n");
3389 " <xsd:maxLength value=\"%d\"/>\n",
3396 " <xsd:restriction base=\"xsd:%s\">\n"
3397 " </xsd:restriction>\n",
3404 " <xsd:restriction base=\"xsd:decimal\">\n"
3405 " <xsd:totalDigits value=\"%d\"/>\n"
3406 " <xsd:fractionDigits value=\"%d\"/>\n"
3407 " </xsd:restriction>\n",
3408 ((typmod -
VARHDRSZ) >> 16) & 0xffff,
3414 " <xsd:restriction base=\"xsd:short\">\n"
3415 " <xsd:maxInclusive value=\"%d\"/>\n"
3416 " <xsd:minInclusive value=\"%d\"/>\n"
3417 " </xsd:restriction>\n",
3418 SHRT_MAX, SHRT_MIN);
3423 " <xsd:restriction base=\"xsd:int\">\n"
3424 " <xsd:maxInclusive value=\"%d\"/>\n"
3425 " <xsd:minInclusive value=\"%d\"/>\n"
3426 " </xsd:restriction>\n",
3432 " <xsd:restriction base=\"xsd:long\">\n"
3435 " </xsd:restriction>\n",
3436 (((uint64) 1) << (
sizeof(int64) * 8 - 1)) - 1,
3437 (((uint64) 1) << (
sizeof(int64) * 8 - 1)));
3442 " <xsd:restriction base=\"xsd:float\"></xsd:restriction>\n");
3447 " <xsd:restriction base=\"xsd:double\"></xsd:restriction>\n");
3452 " <xsd:restriction base=\"xsd:boolean\"></xsd:restriction>\n");
3458 const char *tz = (typeoid ==
TIMETZOID ?
"(+|-)\\p{Nd}{2}:\\p{Nd}{2}" :
"");
3462 " <xsd:restriction base=\"xsd:time\">\n"
3463 " <xsd:pattern value=\"\\p{Nd}{2}:\\p{Nd}{2}:\\p{Nd}{2}(.\\p{Nd}+)?%s\"/>\n"
3464 " </xsd:restriction>\n", tz);
3465 else if (typmod == 0)
3467 " <xsd:restriction base=\"xsd:time\">\n"
3468 " <xsd:pattern value=\"\\p{Nd}{2}:\\p{Nd}{2}:\\p{Nd}{2}%s\"/>\n"
3469 " </xsd:restriction>\n", tz);
3472 " <xsd:restriction base=\"xsd:time\">\n"
3473 " <xsd:pattern value=\"\\p{Nd}{2}:\\p{Nd}{2}:\\p{Nd}{2}.\\p{Nd}{%d}%s\"/>\n"
3474 " </xsd:restriction>\n", typmod -
VARHDRSZ, tz);
3481 const char *tz = (typeoid ==
TIMESTAMPTZOID ?
"(+|-)\\p{Nd}{2}:\\p{Nd}{2}" :
"");
3485 " <xsd:restriction base=\"xsd:dateTime\">\n"
3486 " <xsd:pattern value=\"\\p{Nd}{4}-\\p{Nd}{2}-\\p{Nd}{2}T\\p{Nd}{2}:\\p{Nd}{2}:\\p{Nd}{2}(.\\p{Nd}+)?%s\"/>\n"
3487 " </xsd:restriction>\n", tz);
3488 else if (typmod == 0)
3490 " <xsd:restriction base=\"xsd:dateTime\">\n"
3491 " <xsd:pattern value=\"\\p{Nd}{4}-\\p{Nd}{2}-\\p{Nd}{2}T\\p{Nd}{2}:\\p{Nd}{2}:\\p{Nd}{2}%s\"/>\n"
3492 " </xsd:restriction>\n", tz);
3495 " <xsd:restriction base=\"xsd:dateTime\">\n"
3496 " <xsd:pattern value=\"\\p{Nd}{4}-\\p{Nd}{2}-\\p{Nd}{2}T\\p{Nd}{2}:\\p{Nd}{2}:\\p{Nd}{2}.\\p{Nd}{%d}%s\"/>\n"
3497 " </xsd:restriction>\n", typmod -
VARHDRSZ, tz);
3503 " <xsd:restriction base=\"xsd:date\">\n"
3504 " <xsd:pattern value=\"\\p{Nd}{4}-\\p{Nd}{2}-\\p{Nd}{2}\"/>\n"
3505 " </xsd:restriction>\n");
3512 int32 base_typmod = -1;
3517 " <xsd:restriction base=\"%s\"/>\n",
3535 bool nulls,
bool tableforest,
3536 const char *targetns,
bool top_level)
3602 xml_xmlnodetoxmltype(xmlNodePtr
cur)
3606 if (cur->type == XML_ELEMENT_NODE)
3610 buf = xmlBufferCreate();
3613 xmlNodeDump(buf,
NULL, cur, 0, 1);
3614 result = xmlBuffer_to_xmltype(buf);
3628 str = xmlXPathCastNodeToString(cur);
3662 xml_xpathobjtoxmlarray(xmlXPathObjectPtr xpathobj,
3673 switch (xpathobj->type)
3676 if (xpathobj->nodesetval !=
NULL)
3678 result = xpathobj->nodesetval->nodeNr;
3683 for (i = 0; i < result; i++)
3685 datum =
PointerGetDatum(xml_xmlnodetoxmltype(xpathobj->nodesetval->nodeTab[i]));
3716 elog(
ERROR,
"xpath expression result type %d is unsupported",
3747 volatile xmlParserCtxtPtr ctxt =
NULL;
3748 volatile xmlDocPtr doc =
NULL;
3749 volatile xmlXPathContextPtr xpathctx =
NULL;
3750 volatile xmlXPathCompExprPtr xpathcomp =
NULL;
3751 volatile xmlXPathObjectPtr xpathobj =
NULL;
3756 xmlChar *xpath_expr;
3759 Datum *ns_names_uris;
3760 bool *ns_names_uris_nulls;
3772 ndim = namespaces ?
ARR_NDIM(namespaces) : 0;
3779 if (ndim != 2 || dims[1] != 2)
3781 (
errcode(ERRCODE_DATA_EXCEPTION),
3782 errmsg(
"invalid array for XML namespace mapping"),
3783 errdetail(
"The array must be two-dimensional with length of the second axis equal to 2.")));
3788 &ns_names_uris, &ns_names_uris_nulls,
3791 Assert((ns_count % 2) == 0);
3796 ns_names_uris =
NULL;
3797 ns_names_uris_nulls =
NULL;
3806 (
errcode(ERRCODE_DATA_EXCEPTION),
3807 errmsg(
"empty XPath expression")));
3809 string = (xmlChar *)
palloc((len + 1) *
sizeof(xmlChar));
3810 memcpy(
string, datastr, len);
3813 xpath_expr = (xmlChar *)
palloc((xpath_len + 1) *
sizeof(xmlChar));
3814 memcpy(xpath_expr,
VARDATA(xpath_expr_text), xpath_len);
3815 xpath_expr[xpath_len] =
'\0';
3827 ctxt = xmlNewParserCtxt();
3828 if (ctxt ==
NULL || xmlerrcxt->err_occurred)
3830 "could not allocate parser context");
3831 doc = xmlCtxtReadMemory(ctxt, (
char *)
string, len,
NULL,
NULL, 0);
3832 if (doc ==
NULL || xmlerrcxt->err_occurred)
3834 "could not parse XML document");
3835 xpathctx = xmlXPathNewContext(doc);
3836 if (xpathctx ==
NULL || xmlerrcxt->err_occurred)
3838 "could not allocate XPath context");
3839 xpathctx->node = xmlDocGetRootElement(doc);
3840 if (xpathctx->node ==
NULL || xmlerrcxt->err_occurred)
3842 "could not find root XML element");
3847 for (i = 0; i < ns_count; i++)
3852 if (ns_names_uris_nulls[i * 2] ||
3853 ns_names_uris_nulls[i * 2 + 1])
3855 (
errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
3856 errmsg(
"neither namespace name nor URI may be null")));
3859 if (xmlXPathRegisterNs(xpathctx,
3860 (xmlChar *) ns_name,
3861 (xmlChar *) ns_uri) != 0)
3863 (
errmsg(
"could not register XML namespace with name \"%s\" and URI \"%s\"",
3868 xpathcomp = xmlXPathCompile(xpath_expr);
3869 if (xpathcomp ==
NULL || xmlerrcxt->err_occurred)
3871 "invalid XPath expression");
3880 xpathobj = xmlXPathCompiledEval(xpathcomp, xpathctx);
3881 if (xpathobj ==
NULL || xmlerrcxt->err_occurred)
3883 "could not create XPath object");
3888 if (res_nitems !=
NULL)
3889 *res_nitems = xml_xpathobjtoxmlarray(xpathobj, astate);
3891 (
void) xml_xpathobjtoxmlarray(xpathobj, astate);
3896 xmlXPathFreeObject(xpathobj);
3898 xmlXPathFreeCompExpr(xpathcomp);
3900 xmlXPathFreeContext(xpathctx);
3904 xmlFreeParserCtxt(ctxt);
3912 xmlXPathFreeObject(xpathobj);
3913 xmlXPathFreeCompExpr(xpathcomp);
3914 xmlXPathFreeContext(xpathctx);
3916 xmlFreeParserCtxt(ctxt);
3939 xpath_internal(xpath_expr_text, data, namespaces,
3940 &res_nitems, &astate);
3942 if (res_nitems == 0)
3964 xpath_internal(xpath_expr_text, data,
NULL,
3988 xpath_internal(xpath_expr_text, data, namespaces,
4007 volatile xmlDocPtr doc =
NULL;