49#include <libxml/chvalid.h>
50#include <libxml/entities.h>
51#include <libxml/parser.h>
52#include <libxml/parserInternals.h>
53#include <libxml/tree.h>
54#include <libxml/uri.h>
55#include <libxml/xmlerror.h>
56#include <libxml/xmlsave.h>
57#include <libxml/xmlversion.h>
58#include <libxml/xmlwriter.h>
59#include <libxml/xpath.h>
60#include <libxml/xpathInternals.h>
67#if LIBXML_VERSION >= 20704
68#define HAVE_XMLSTRUCTUREDERRORCONTEXT 1
74#if LIBXML_VERSION >= 21200
75#define PgXmlErrorPtr const xmlError *
77#define PgXmlErrorPtr xmlErrorPtr
114#define ERRCXT_MAGIC 68275028
125 xmlStructuredErrorFunc saved_errfunc;
128 xmlExternalEntityLoader saved_entityfunc;
131static xmlParserInputPtr xmlPgEntityLoader(
const char *URL,
const char *ID,
132 xmlParserCtxtPtr ctxt);
134 int sqlcode,
const char *msg);
135static void xml_errorHandler(
void *
data, PgXmlErrorPtr
error);
136static int errdetail_for_xml_code(
int code);
140#ifdef USE_LIBXMLCONTEXT
144static void xml_memory_init(
void);
145static void *xml_palloc(
size_t size);
146static void *xml_repalloc(
void *ptr,
size_t size);
147static void xml_pfree(
void *ptr);
148static char *xml_pstrdup(
const char *
string);
151static xmlChar *xml_text2xmlChar(
text *in);
152static int parse_xml_decl(
const xmlChar *
str,
size_t *lenp,
153 xmlChar **version, xmlChar **
encoding,
int *standalone);
154static bool print_xml_decl(
StringInfo buf,
const xmlChar *version,
156static bool xml_doctype_in_content(
const xmlChar *
str);
158 bool preserve_whitespace,
int encoding,
160 xmlNodePtr *parsed_nodes,
163static int xml_xpathobjtoxmlarray(xmlXPathObjectPtr xpathobj,
166static xmlChar *pg_xmlCharStrndup(
const char *
str,
size_t len);
170 const char *xmlschema,
const char *targetns,
174 const char *xmlschema,
bool nulls,
bool tableforest,
175 const char *targetns,
bool top_level);
177 bool nulls,
bool tableforest,
const char *targetns);
179 List *relid_list,
bool nulls,
180 bool tableforest,
const char *targetns);
182 bool nulls,
bool tableforest,
183 const char *targetns);
188 char *tablename,
bool nulls,
bool tableforest,
189 const char *targetns,
bool top_level);
194#define XMLTABLE_CONTEXT_MAGIC 46922182
195typedef struct XmlTableBuilderData
201 xmlParserCtxtPtr ctxt;
203 xmlXPathContextPtr xpathcxt;
204 xmlXPathCompExprPtr xpathcomp;
205 xmlXPathObjectPtr xpathobj;
206 xmlXPathCompExprPtr *xpathscomp;
207} XmlTableBuilderData;
216 const char *path,
int colnum);
219 Oid typid,
int32 typmod,
bool *isnull);
234#define NO_XML_SUPPORT() \
236 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), \
237 errmsg("unsupported XML feature"), \
238 errdetail("This functionality requires the server to be built with libxml support.")))
242#define NAMESPACE_XSD "http://www.w3.org/2001/XMLSchema"
243#define NAMESPACE_XSI "http://www.w3.org/2001/XMLSchema-instance"
244#define NAMESPACE_SQLXML "http://standards.iso.org/iso/9075/2003/sqlxml"
250xmlChar_to_encoding(
const xmlChar *encoding_name)
256 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
257 errmsg(
"invalid encoding name \"%s\"",
258 (
const char *) encoding_name)));
288 NULL, NULL, fcinfo->context);
300#define PG_XML_DEFAULT_VERSION "1.0"
321 if ((res_code = parse_xml_decl((xmlChar *)
str,
322 &
len, &version, NULL, &standalone)) == 0)
328 if (!print_xml_decl(&
buf, version, target_encoding, standalone))
348 errdetail_for_xml_code(res_code));
379 xmlChar *encodingStr = NULL;
387 nbytes =
buf->len -
buf->cursor;
401 parse_xml_decl((
const xmlChar *)
str, NULL, NULL, &encodingStr, NULL);
481xmlBuffer_to_xmltype(xmlBufferPtr
buf)
484 xmlBufferLength(
buf));
502 if (argdata[
i] ==
'-' && argdata[
i - 1] ==
'-')
504 (
errcode(ERRCODE_INVALID_XML_COMMENT),
505 errmsg(
"invalid XML comment")));
507 if (
len > 0 && argdata[
len - 1] ==
'-')
509 (
errcode(ERRCODE_INVALID_XML_COMMENT),
510 errmsg(
"invalid XML comment")));
531 volatile xmlChar *xmlbuf = NULL;
539 xmlbuf = xmlEncodeSpecialChars(NULL, xml_text2xmlChar(
arg));
541 if (xmlbuf == NULL || xmlerrcxt->err_occurred)
543 "could not allocate xmlChar");
546 xmlStrlen((
const xmlChar *) xmlbuf));
551 xmlFree((xmlChar *) xmlbuf);
558 xmlFree((xmlChar *) xmlbuf);
577 int global_standalone = 1;
578 xmlChar *global_version = NULL;
579 bool global_version_no_value =
false;
595 parse_xml_decl((xmlChar *)
str, &
len, &version, NULL, &standalone);
597 if (standalone == 0 && global_standalone == 1)
598 global_standalone = 0;
600 global_standalone = -1;
603 global_version_no_value =
true;
604 else if (!global_version)
605 global_version = version;
606 else if (xmlStrcmp(version, global_version) != 0)
607 global_version_no_value =
true;
613 if (!global_version_no_value || global_standalone >= 0)
619 print_xml_decl(&buf2,
620 (!global_version_no_value) ? global_version : NULL,
680 text *
volatile result;
683 xmlNodePtr content_nodes;
684 volatile xmlBufferPtr
buf = NULL;
685 volatile xmlSaveCtxtPtr ctxt = NULL;
709 &parsed_xmloptiontype, &content_nodes,
710 (
Node *) &escontext);
717 (
errcode(ERRCODE_NOT_AN_XML_DOCUMENT),
718 errmsg(
"not an XML document")));
741 buf = xmlBufferCreate();
743 if (
buf == NULL || xmlerrcxt->err_occurred)
745 "could not allocate xmlBuffer");
748 parse_xml_decl(xml_text2xmlChar(
data), &decl_len, NULL, NULL, NULL);
757 ctxt = xmlSaveToBuffer(
buf, NULL,
758 XML_SAVE_NO_DECL | XML_SAVE_FORMAT);
760 ctxt = xmlSaveToBuffer(
buf, NULL,
763 if (ctxt == NULL || xmlerrcxt->err_occurred)
765 "could not allocate xmlSaveCtxt");
770 if (xmlSaveDoc(ctxt, doc) == -1 || xmlerrcxt->err_occurred)
772 "could not save document to xmlBuffer");
774 else if (content_nodes != NULL)
786 root = xmlNewNode(NULL, (
const xmlChar *)
"content-root");
787 if (
root == NULL || xmlerrcxt->err_occurred)
789 "could not allocate xml node");
795 oldroot = xmlDocSetRootElement(doc,
root);
797 xmlFreeNode(oldroot);
799 if (xmlAddChildList(
root, content_nodes) == NULL ||
800 xmlerrcxt->err_occurred)
802 "could not append xml node list");
811 newline = xmlNewDocText(NULL, (
const xmlChar *)
"\n");
812 if (
newline == NULL || xmlerrcxt->err_occurred)
814 "could not allocate xml node");
816 for (xmlNodePtr node =
root->children; node; node = node->next)
819 if (node->type != XML_TEXT_NODE && node->prev != NULL)
821 if (xmlSaveTree(ctxt,
newline) == -1 || xmlerrcxt->err_occurred)
825 "could not save newline to xmlBuffer");
829 if (xmlSaveTree(ctxt, node) == -1 || xmlerrcxt->err_occurred)
833 "could not save content to xmlBuffer");
840 if (xmlSaveClose(ctxt) == -1 || xmlerrcxt->err_occurred)
844 "could not close xmlSaveCtxtPtr");
852 const char *
str = (
const char *) xmlBufferContent(
buf);
853 int len = xmlBufferLength(
buf);
855 while (
len > 0 && (
str[
len - 1] ==
'\n' ||
862 result = (
text *) xmlBuffer_to_xmltype(
buf);
894 Datum *named_argvalue,
bool *named_argnull,
895 Datum *argvalue,
bool *argnull)
899 List *named_arg_strings;
905 volatile xmlBufferPtr
buf = NULL;
906 volatile xmlTextWriterPtr writer = NULL;
915 named_arg_strings =
NIL;
922 if (named_argnull[
i])
928 named_arg_strings =
lappend(named_arg_strings,
str);
954 buf = xmlBufferCreate();
955 if (
buf == NULL || xmlerrcxt->err_occurred)
957 "could not allocate xmlBuffer");
958 writer = xmlNewTextWriterMemory(
buf, 0);
959 if (writer == NULL || xmlerrcxt->err_occurred)
961 "could not allocate xmlTextWriter");
963 if (xmlTextWriterStartElement(writer, (xmlChar *) xexpr->name) < 0 ||
964 xmlerrcxt->err_occurred)
966 "could not start xml element");
968 forboth(
arg, named_arg_strings, narg, xexpr->arg_names)
975 if (xmlTextWriterWriteAttribute(writer,
977 (xmlChar *)
str) < 0 ||
978 xmlerrcxt->err_occurred)
980 "could not write xml attribute");
984 foreach(
arg, arg_strings)
988 if (xmlTextWriterWriteRaw(writer, (xmlChar *)
str) < 0 ||
989 xmlerrcxt->err_occurred)
991 "could not write raw xml text");
994 if (xmlTextWriterEndElement(writer) < 0 ||
995 xmlerrcxt->err_occurred)
997 "could not end xml element");
1000 xmlFreeTextWriter(writer);
1003 result = xmlBuffer_to_xmltype(
buf);
1008 xmlFreeTextWriter(writer);
1036 doc = xml_parse(
data, xmloption_arg, preserve_whitespace,
1049xmlpi(
const char *target,
text *
arg,
bool arg_is_null,
bool *result_is_null)
1057 (
errcode(ERRCODE_INVALID_XML_PROCESSING_INSTRUCTION),
1058 errmsg(
"invalid XML processing instruction"),
1059 errdetail(
"XML processing instruction target name cannot be \"%s\".", target)));
1065 *result_is_null = arg_is_null;
1066 if (*result_is_null)
1078 if (strstr(
string,
"?>") != NULL)
1080 (
errcode(ERRCODE_INVALID_XML_PROCESSING_INSTRUCTION),
1081 errmsg(
"invalid XML processing instruction"),
1082 errdetail(
"XML processing instruction cannot contain \"?>\".")));
1106 xmlChar *orig_version;
1107 int orig_standalone;
1113 parse_xml_decl((xmlChar *)
str, &
len, &orig_version, NULL, &orig_standalone);
1116 orig_version = xml_text2xmlChar(version);
1118 orig_version = NULL;
1123 orig_standalone = 1;
1126 orig_standalone = 0;
1129 orig_standalone = -1;
1137 print_xml_decl(&
buf, orig_version, 0, orig_standalone);
1160 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1161 errmsg(
"xmlvalidate is not implemented")));
1205 static bool first_time =
true;
1215 if (
sizeof(
char) !=
sizeof(xmlChar))
1217 (
errmsg(
"could not initialize XML library"),
1218 errdetail(
"libxml2 has incompatible char type: sizeof(char)=%zu, sizeof(xmlChar)=%zu.",
1219 sizeof(
char),
sizeof(xmlChar))));
1221#ifdef USE_LIBXMLCONTEXT
1227 LIBXML_TEST_VERSION;
1259 errcxt->magic = ERRCXT_MAGIC;
1260 errcxt->strictness = strictness;
1261 errcxt->err_occurred =
false;
1271 errcxt->saved_errfunc = xmlStructuredError;
1273#ifdef HAVE_XMLSTRUCTUREDERRORCONTEXT
1274 errcxt->saved_errcxt = xmlStructuredErrorContext;
1276 errcxt->saved_errcxt = xmlGenericErrorContext;
1279 xmlSetStructuredErrorFunc(errcxt, xml_errorHandler);
1295#ifdef HAVE_XMLSTRUCTUREDERRORCONTEXT
1296 new_errcxt = xmlStructuredErrorContext;
1298 new_errcxt = xmlGenericErrorContext;
1301 if (new_errcxt != errcxt)
1303 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1304 errmsg(
"could not set up XML error handler"),
1305 errhint(
"This probably indicates that the version of libxml2"
1306 " being used is not compatible with the libxml2"
1307 " header files that PostgreSQL was built with.")));
1313 errcxt->saved_entityfunc = xmlGetExternalEntityLoader();
1314 xmlSetExternalEntityLoader(xmlPgEntityLoader);
1335 Assert(errcxt->magic == ERRCXT_MAGIC);
1342 Assert(!errcxt->err_occurred || isError);
1349#ifdef HAVE_XMLSTRUCTUREDERRORCONTEXT
1350 cur_errcxt = xmlStructuredErrorContext;
1352 cur_errcxt = xmlGenericErrorContext;
1355 if (cur_errcxt != errcxt)
1356 elog(
WARNING,
"libxml error handling state is out of sync with xml.c");
1359 xmlSetStructuredErrorFunc(errcxt->saved_errcxt, errcxt->saved_errfunc);
1360 xmlSetExternalEntityLoader(errcxt->saved_entityfunc);
1369 pfree(errcxt->err_buf.data);
1380 return errcxt->err_occurred;
1393#define CHECK_XML_SPACE(p) \
1395 if (!xmlIsBlank_ch(*(p))) \
1396 return XML_ERR_SPACE_REQUIRED; \
1399#define SKIP_XML_SPACE(p) \
1400 while (xmlIsBlank_ch(*(p))) (p)++
1404#define PG_XMLISNAMECHAR(c) \
1405 (xmlIsBaseChar_ch(c) || xmlIsIdeographicQ(c) \
1406 || xmlIsDigit_ch(c) \
1407 || c == '.' || c == '-' || c == '_' || c == ':' \
1408 || xmlIsCombiningQ(c) \
1409 || xmlIsExtender_ch(c))
1413xml_pnstrdup(
const xmlChar *
str,
size_t len)
1417 result = (xmlChar *)
palloc((
len + 1) *
sizeof(xmlChar));
1418 memcpy(result,
str,
len *
sizeof(xmlChar));
1425pg_xmlCharStrndup(
const char *
str,
size_t len)
1429 result = (xmlChar *)
palloc((
len + 1) *
sizeof(xmlChar));
1430 memcpy(result,
str,
len);
1442xml_pstrdup_and_free(xmlChar *
str)
1471parse_xml_decl(
const xmlChar *
str,
size_t *lenp,
1472 xmlChar **version, xmlChar **
encoding,
int *standalone)
1475 const xmlChar *save_p;
1498 if (xmlStrncmp(p, (xmlChar *)
"<?xml", 5) != 0)
1510 utf8char = xmlGetUTF8Char(p + 5, &utf8len);
1511 if (PG_XMLISNAMECHAR(utf8char))
1519 if (xmlStrncmp(p, (xmlChar *)
"version", 7) != 0)
1520 return XML_ERR_VERSION_MISSING;
1524 return XML_ERR_VERSION_MISSING;
1528 if (*p ==
'\'' || *p ==
'"')
1532 q = xmlStrchr(p + 1, *p);
1534 return XML_ERR_VERSION_MISSING;
1537 *version = xml_pnstrdup(p + 1, q - p - 1);
1541 return XML_ERR_VERSION_MISSING;
1546 if (xmlStrncmp(p, (xmlChar *)
"encoding", 8) == 0)
1548 CHECK_XML_SPACE(save_p);
1552 return XML_ERR_MISSING_ENCODING;
1556 if (*p ==
'\'' || *p ==
'"')
1560 q = xmlStrchr(p + 1, *p);
1562 return XML_ERR_MISSING_ENCODING;
1565 *
encoding = xml_pnstrdup(p + 1, q - p - 1);
1569 return XML_ERR_MISSING_ENCODING;
1579 if (xmlStrncmp(p, (xmlChar *)
"standalone", 10) == 0)
1581 CHECK_XML_SPACE(save_p);
1585 return XML_ERR_STANDALONE_VALUE;
1588 if (xmlStrncmp(p, (xmlChar *)
"'yes'", 5) == 0 ||
1589 xmlStrncmp(p, (xmlChar *)
"\"yes\"", 5) == 0)
1595 else if (xmlStrncmp(p, (xmlChar *)
"'no'", 4) == 0 ||
1596 xmlStrncmp(p, (xmlChar *)
"\"no\"", 4) == 0)
1603 return XML_ERR_STANDALONE_VALUE;
1611 if (xmlStrncmp(p, (xmlChar *)
"?>", 2) != 0)
1612 return XML_ERR_XMLDECL_NOT_FINISHED;
1620 return XML_ERR_INVALID_CHAR;
1649 || standalone != -1)
1668 if (standalone == 1)
1670 else if (standalone == 0)
1710xml_doctype_in_content(
const xmlChar *
str)
1712 const xmlChar *p =
str;
1728 if (xmlStrncmp(p, (xmlChar *)
"DOCTYPE", 7) == 0)
1732 if (xmlStrncmp(p, (xmlChar *)
"--", 2) != 0)
1735 p = xmlStrstr(p + 2, (xmlChar *)
"--");
1736 if (!p || p[2] !=
'>')
1749 e = xmlStrstr(p, (xmlChar *)
"?>");
1787 bool preserve_whitespace,
int encoding,
1788 XmlOptionType *parsed_xmloptiontype, xmlNodePtr *parsed_nodes,
1793 xmlChar *utf8string;
1795 volatile xmlParserCtxtPtr ctxt = NULL;
1796 volatile xmlDocPtr doc = NULL;
1797 volatile int save_keep_blanks = -1;
1804 string = xml_text2xmlChar(
data);
1824 bool parse_as_document =
false;
1827 xmlChar *version = NULL;
1835 parse_as_document =
true;
1839 res_code = parse_xml_decl(utf8string,
1840 &count, &version, NULL, &standalone);
1844 errcode(ERRCODE_INVALID_XML_CONTENT),
1846 errdetail_for_xml_code(res_code));
1851 if (xml_doctype_in_content(utf8string + count))
1852 parse_as_document =
true;
1856 if (parsed_xmloptiontype != NULL)
1859 if (parsed_nodes != NULL)
1860 *parsed_nodes = NULL;
1862 if (parse_as_document)
1867 ctxt = xmlNewParserCtxt();
1868 if (ctxt == NULL || xmlerrcxt->err_occurred)
1870 "could not allocate parser context");
1881 options = XML_PARSE_NOENT | XML_PARSE_DTDATTR
1882 | (preserve_whitespace ? 0 : XML_PARSE_NOBLANKS);
1884 doc = xmlCtxtReadDoc(ctxt, utf8string,
1889 if (doc == NULL || xmlerrcxt->err_occurred)
1893 xml_errsave(escontext, xmlerrcxt,
1894 ERRCODE_INVALID_XML_DOCUMENT,
1895 "invalid XML document");
1897 xml_errsave(escontext, xmlerrcxt,
1898 ERRCODE_INVALID_XML_CONTENT,
1899 "invalid XML content");
1906 doc = xmlNewDoc(version);
1907 if (doc == NULL || xmlerrcxt->err_occurred)
1909 "could not allocate XML document");
1911 Assert(doc->encoding == NULL);
1912 doc->encoding = xmlStrdup((
const xmlChar *)
"UTF-8");
1913 if (doc->encoding == NULL || xmlerrcxt->err_occurred)
1915 "could not allocate XML document");
1916 doc->standalone = standalone;
1919 save_keep_blanks = xmlKeepBlanksDefault(preserve_whitespace ? 1 : 0);
1922 if (*(utf8string + count))
1924 res_code = xmlParseBalancedChunkMemory(doc, NULL, NULL, 0,
1927 if (res_code != 0 || xmlerrcxt->err_occurred)
1929 xml_errsave(escontext, xmlerrcxt,
1930 ERRCODE_INVALID_XML_CONTENT,
1931 "invalid XML content");
1942 if (save_keep_blanks != -1)
1943 xmlKeepBlanksDefault(save_keep_blanks);
1947 xmlFreeParserCtxt(ctxt);
1955 if (save_keep_blanks != -1)
1956 xmlKeepBlanksDefault(save_keep_blanks);
1959 xmlFreeParserCtxt(ctxt);
1971xml_text2xmlChar(
text *in)
1977#ifdef USE_LIBXMLCONTEXT
1984xml_memory_init(
void)
1987 if (LibxmlContext == NULL)
1993 xmlMemSetup(xml_pfree, xml_palloc, xml_repalloc, xml_pstrdup);
2000xml_palloc(
size_t size)
2007xml_repalloc(
void *ptr,
size_t size)
2023xml_pstrdup(
const char *
string)
2041static xmlParserInputPtr
2042xmlPgEntityLoader(
const char *URL,
const char *ID,
2043 xmlParserCtxtPtr ctxt)
2045 return xmlNewStringInputStream(ctxt, (
const xmlChar *)
"");
2065 if (errcxt->magic != ERRCXT_MAGIC)
2066 elog(
ERROR,
"xml_ereport called with invalid PgXmlErrorContext");
2069 errcxt->err_occurred =
false;
2072 if (errcxt->err_buf.len > 0)
2073 detail = errcxt->err_buf.data;
2098 int sqlcode,
const char *msg)
2103 if (errcxt->magic != ERRCXT_MAGIC)
2104 elog(
ERROR,
"xml_errsave called with invalid PgXmlErrorContext");
2107 errcxt->err_occurred =
false;
2110 if (errcxt->err_buf.len > 0)
2111 detail = errcxt->err_buf.data;
2126xml_errorHandler(
void *
data, PgXmlErrorPtr
error)
2129 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr)
error->ctxt;
2130 xmlParserInputPtr
input = (ctxt != NULL) ? ctxt->input : NULL;
2131 xmlNodePtr node =
error->node;
2132 const xmlChar *
name = (node != NULL &&
2133 node->type == XML_ELEMENT_NODE) ? node->name : NULL;
2134 int domain =
error->domain;
2135 int level =
error->level;
2144 if (xmlerrcxt->magic != ERRCXT_MAGIC)
2145 elog(
FATAL,
"xml_errorHandler called with invalid PgXmlErrorContext");
2155 switch (
error->code)
2157 case XML_WAR_NS_URI:
2158 level = XML_ERR_ERROR;
2159 domain = XML_FROM_NAMESPACE;
2162 case XML_ERR_NS_DECL_ERROR:
2163 case XML_WAR_NS_URI_RELATIVE:
2164 case XML_WAR_NS_COLUMN:
2165 case XML_NS_ERR_XML_NAMESPACE:
2166 case XML_NS_ERR_UNDEFINED_NAMESPACE:
2167 case XML_NS_ERR_QNAME:
2168 case XML_NS_ERR_ATTRIBUTE_REDEFINED:
2169 case XML_NS_ERR_EMPTY:
2170 domain = XML_FROM_NAMESPACE;
2177 case XML_FROM_PARSER:
2186 if (
error->code == XML_ERR_NOT_WELL_BALANCED &&
2187 xmlerrcxt->err_occurred)
2192 case XML_FROM_MEMORY:
2199 if (
error->code == XML_WAR_UNDECLARED_ENTITY)
2215 if (
error->line > 0)
2219 if (
error->message != NULL)
2237 xmlGenericErrorFunc errFuncSaved = xmlGenericError;
2238 void *errCtxSaved = xmlGenericErrorContext;
2240 xmlSetGenericErrorFunc(errorBuf,
2244 appendStringInfoLineSeparator(errorBuf);
2246 xmlParserPrintFileContext(
input);
2249 xmlSetGenericErrorFunc(errCtxSaved, errFuncSaved);
2253 chopStringInfoNewlines(errorBuf);
2265 appendStringInfoLineSeparator(&xmlerrcxt->err_buf);
2281 if (level >= XML_ERR_ERROR)
2283 appendStringInfoLineSeparator(&xmlerrcxt->err_buf);
2287 xmlerrcxt->err_occurred =
true;
2289 else if (level >= XML_ERR_WARNING)
2314errdetail_for_xml_code(
int code)
2320 case XML_ERR_INVALID_CHAR:
2323 case XML_ERR_SPACE_REQUIRED:
2326 case XML_ERR_STANDALONE_VALUE:
2327 det =
gettext_noop(
"standalone accepts only 'yes' or 'no'.");
2329 case XML_ERR_VERSION_MISSING:
2330 det =
gettext_noop(
"Malformed declaration: missing version.");
2332 case XML_ERR_MISSING_ENCODING:
2333 det =
gettext_noop(
"Missing encoding in text declaration.");
2335 case XML_ERR_XMLDECL_NOT_FINISHED:
2336 det =
gettext_noop(
"Parsing XML declaration: '?>' expected.");
2339 det =
gettext_noop(
"Unrecognized libxml error code: %d.");
2353 while (
str->len > 0 &&
str->data[
str->len - 1] ==
'\n')
2354 str->data[--
str->len] =
'\0';
2364 chopStringInfoNewlines(
str);
2374sqlchar_to_unicode(
const char *s)
2385 if (utf8string != s)
2396 return (xmlIsBaseCharQ(
c) || xmlIsIdeographicQ(
c)
2397 ||
c ==
'_' ||
c ==
':');
2405 return (xmlIsBaseCharQ(
c) || xmlIsIdeographicQ(
c)
2407 ||
c ==
'.' ||
c ==
'-' ||
c ==
'_' ||
c ==
':'
2408 || xmlIsCombiningQ(
c)
2409 || xmlIsExtenderQ(
c));
2429 Assert(fully_escaped || !escape_period);
2435 if (*p ==
':' && (p ==
ident || fully_escaped))
2437 else if (*p ==
'_' && *(p + 1) ==
'x')
2439 else if (fully_escaped && p ==
ident &&
2447 else if (escape_period && *p ==
'.')
2451 pg_wchar u = sqlchar_to_unicode(p);
2454 ? !is_valid_xml_namefirst(u)
2455 : !is_valid_xml_namechar(u))
2483 if (*p ==
'_' && *(p + 1) ==
'x'
2484 && isxdigit((
unsigned char) *(p + 2))
2485 && isxdigit((
unsigned char) *(p + 3))
2486 && isxdigit((
unsigned char) *(p + 4))
2487 && isxdigit((
unsigned char) *(p + 5))
2493 sscanf(p + 2,
"%X", &u);
2536 elmlen, elmbyval, elmalign,
2537 &elem_values, &elem_nulls,
2542 for (
i = 0;
i < num_elems;
i++)
2591 (
errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2592 errmsg(
"date out of range"),
2593 errdetail(
"XML does not support infinite date values.")));
2613 (
errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2614 errmsg(
"timestamp out of range"),
2615 errdetail(
"XML does not support infinite timestamp values.")));
2620 (
errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2621 errmsg(
"timestamp out of range")));
2626 case TIMESTAMPTZOID:
2632 const char *tzn = NULL;
2640 (
errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2641 errmsg(
"timestamp out of range"),
2642 errdetail(
"XML does not support infinite timestamp values.")));
2647 (
errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2648 errmsg(
"timestamp out of range")));
2658 volatile xmlBufferPtr
buf = NULL;
2659 volatile xmlTextWriterPtr writer = NULL;
2666 buf = xmlBufferCreate();
2667 if (
buf == NULL || xmlerrcxt->err_occurred)
2669 "could not allocate xmlBuffer");
2670 writer = xmlNewTextWriterMemory(
buf, 0);
2671 if (writer == NULL || xmlerrcxt->err_occurred)
2673 "could not allocate xmlTextWriter");
2676 xmlTextWriterWriteBase64(writer,
VARDATA_ANY(bstr),
2679 xmlTextWriterWriteBinHex(writer,
VARDATA_ANY(bstr),
2683 xmlFreeTextWriter(writer);
2686 result =
pstrdup((
const char *) xmlBufferContent(
buf));
2691 xmlFreeTextWriter(writer);
2718 if (
type == XMLOID || !xml_escape_strings)
2741 for (p =
str; *p; p++)
2769 size_t len = strlen(s) + 1;
2772 memcpy(ret, s,
len);
2832 elog(
ERROR,
"SPI_execute returned %s for %s",
2859 " WHERE relnamespace = %u AND relkind IN ("
2863 " AND pg_catalog.has_table_privilege (oid, 'SELECT')"
2864 " ORDER BY relname;",
nspid);
2874#define XML_VISIBLE_SCHEMAS_EXCLUDE "(nspname ~ '^pg_' OR nspname = 'information_schema')"
2876#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
2891 " WHERE relkind IN ("
2895 " AND pg_catalog.has_table_privilege(pg_class.oid, 'SELECT')"
2907 const char *xmlschema,
bool nulls,
bool tableforest,
2908 const char *targetns,
bool top_level)
2917 xmlschema, nulls, tableforest,
2918 targetns, top_level);
2945 NULL, nulls, tableforest,
2975 (
errcode(ERRCODE_UNDEFINED_CURSOR),
2976 errmsg(
"cursor \"%s\" does not exist",
name)));
2981 tableforest, targetns,
true);
3006 const char *xmlschema,
const char *targetns,
3010 Assert(top_level || !xmlschema);
3016 if (strlen(targetns) > 0)
3022 if (strlen(targetns) > 0)
3040 const char *xmlschema,
bool nulls,
bool tableforest,
3041 const char *targetns,
bool top_level)
3057 (
errcode(ERRCODE_DATA_EXCEPTION),
3058 errmsg(
"invalid query")));
3063 targetns, top_level);
3072 tableforest, targetns, top_level);
3095 tableforest, targetns);
3116 elog(
ERROR,
"SPI_prepare(\"%s\") failed", query);
3119 elog(
ERROR,
"SPI_cursor_open(\"%s\") failed", query);
3123 tableforest, targetns));
3138 const char *xmlschema;
3145 (
errcode(ERRCODE_UNDEFINED_CURSOR),
3146 errmsg(
"cursor \"%s\" does not exist",
name)));
3149 (
errcode(ERRCODE_INVALID_CURSOR_STATE),
3150 errmsg(
"portal \"%s\" does not return tuples",
name)));
3154 tableforest, targetns));
3169 const char *xmlschema;
3173 tableforest, targetns);
3177 xmlschema, nulls, tableforest,
3190 const char *xmlschema;
3197 elog(
ERROR,
"SPI_prepare(\"%s\") failed", query);
3200 elog(
ERROR,
"SPI_cursor_open(\"%s\") failed", query);
3208 xmlschema, nulls, tableforest,
3220 bool tableforest,
const char *targetns,
bool top_level)
3241 foreach(cell, relid_list)
3276 nulls, tableforest, targetns,
true)));
3289 if (strlen(targetns) > 0)
3292 " targetNamespace=\"%s\"\n"
3293 " elementFormDefault=\"qualified\"",
3309 bool tableforest,
const char *targetns)
3328 foreach(cell, relid_list)
3342 nulls, tableforest, targetns));
3361 nulls, tableforest, targetns)));
3380 tableforest, targetns);
3383 xmlschema->
data, nulls,
3384 tableforest, targetns,
true)));
3395 bool tableforest,
const char *targetns)
3416 foreach(cell, nspid_list)
3422 tableforest, targetns,
false);
3444 tableforest, targetns)));
3450 const char *targetns)
3468 foreach(cell, relid_list)
3499 tableforest, targetns)));
3514 nulls, tableforest, targetns)));
3555 bool tableforest,
const char *targetns)
3559 char *tabletypename;
3572 elog(
ERROR,
"cache lookup failed for relation %u", relid);
3597 tabletypename =
"TableType";
3598 rowtypename =
"RowType";
3607 "<xsd:complexType name=\"%s\">\n"
3608 " <xsd:sequence>\n",
3611 for (
i = 0;
i < tupdesc->
natts;
i++)
3615 if (att->attisdropped)
3618 " <xsd:element name=\"%s\" type=\"%s\"%s></xsd:element>\n",
3622 nulls ?
" nillable=\"true\"" :
" minOccurs=\"0\"");
3626 " </xsd:sequence>\n"
3627 "</xsd:complexType>\n\n");
3632 "<xsd:complexType name=\"%s\">\n"
3634 " <xsd:element name=\"row\" type=\"%s\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n"
3635 " </xsd:sequence>\n"
3636 "</xsd:complexType>\n\n",
3637 tabletypename, rowtypename);
3640 "<xsd:element name=\"%s\" type=\"%s\"/>\n\n",
3641 xmltn, tabletypename);
3645 "<xsd:element name=\"%s\" type=\"%s\"/>\n\n",
3646 xmltn, rowtypename);
3660 bool tableforest,
const char *targetns)
3665 char *schematypename;
3682 "<xsd:complexType name=\"%s\">\n", schematypename);
3688 " <xsd:sequence>\n");
3690 foreach(cell, relid_list)
3702 " <xsd:element name=\"%s\" type=\"%s\"/>\n",
3703 xmltn, tabletypename);
3706 " <xsd:element name=\"%s\" type=\"%s\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n",
3707 xmltn, tabletypename);
3715 " </xsd:sequence>\n");
3717 "</xsd:complexType>\n\n");
3720 "<xsd:element name=\"%s\" type=\"%s\"/>\n\n",
3721 xmlsn, schematypename);
3733 bool tableforest,
const char *targetns)
3737 char *catalogtypename;
3753 "<xsd:complexType name=\"%s\">\n", catalogtypename);
3757 foreach(cell, nspid_list)
3768 " <xsd:element name=\"%s\" type=\"%s\"/>\n",
3769 xmlsn, schematypename);
3775 "</xsd:complexType>\n\n");
3778 "<xsd:element name=\"%s\" type=\"%s\"/>\n\n",
3779 xmlcn, catalogtypename);
3814 ((typmod -
VARHDRSZ) >> 16) & 0xffff,
3853 case TIMESTAMPTZOID:
3872 elog(
ERROR,
"cache lookup failed for type %u", typeoid);
3902 foreach(cell0, tupdesc_list)
3906 for (
i = 0;
i < tupdesc->
natts;
i++)
3910 if (att->attisdropped)
3917 foreach(cell0, uniquetypes)
3922 if (basetypid != typid)
3929 foreach(cell0, uniquetypes)
3956 if (typeoid == XMLOID)
3959 "<xsd:complexType mixed=\"true\">\n"
3961 " <xsd:any name=\"element\" minOccurs=\"0\" maxOccurs=\"unbounded\" processContents=\"skip\"/>\n"
3962 " </xsd:sequence>\n"
3963 "</xsd:complexType>\n");
3968 "<xsd:simpleType name=\"%s\">\n",
typename);
3976 " <xsd:restriction base=\"xsd:string\">\n");
3979 " <xsd:maxLength value=\"%d\"/>\n",
3986 " <xsd:restriction base=\"xsd:%s\">\n"
3987 " </xsd:restriction>\n",
3994 " <xsd:restriction base=\"xsd:decimal\">\n"
3995 " <xsd:totalDigits value=\"%d\"/>\n"
3996 " <xsd:fractionDigits value=\"%d\"/>\n"
3997 " </xsd:restriction>\n",
3998 ((typmod -
VARHDRSZ) >> 16) & 0xffff,
4004 " <xsd:restriction base=\"xsd:short\">\n"
4005 " <xsd:maxInclusive value=\"%d\"/>\n"
4006 " <xsd:minInclusive value=\"%d\"/>\n"
4007 " </xsd:restriction>\n",
4008 SHRT_MAX, SHRT_MIN);
4013 " <xsd:restriction base=\"xsd:int\">\n"
4014 " <xsd:maxInclusive value=\"%d\"/>\n"
4015 " <xsd:minInclusive value=\"%d\"/>\n"
4016 " </xsd:restriction>\n",
4022 " <xsd:restriction base=\"xsd:long\">\n"
4025 " </xsd:restriction>\n",
4032 " <xsd:restriction base=\"xsd:float\"></xsd:restriction>\n");
4037 " <xsd:restriction base=\"xsd:double\"></xsd:restriction>\n");
4042 " <xsd:restriction base=\"xsd:boolean\"></xsd:restriction>\n");
4048 const char *tz = (typeoid == TIMETZOID ?
"(\\+|-)\\p{Nd}{2}:\\p{Nd}{2}" :
"");
4052 " <xsd:restriction base=\"xsd:time\">\n"
4053 " <xsd:pattern value=\"\\p{Nd}{2}:\\p{Nd}{2}:\\p{Nd}{2}(.\\p{Nd}+)?%s\"/>\n"
4054 " </xsd:restriction>\n", tz);
4055 else if (typmod == 0)
4057 " <xsd:restriction base=\"xsd:time\">\n"
4058 " <xsd:pattern value=\"\\p{Nd}{2}:\\p{Nd}{2}:\\p{Nd}{2}%s\"/>\n"
4059 " </xsd:restriction>\n", tz);
4062 " <xsd:restriction base=\"xsd:time\">\n"
4063 " <xsd:pattern value=\"\\p{Nd}{2}:\\p{Nd}{2}:\\p{Nd}{2}.\\p{Nd}{%d}%s\"/>\n"
4064 " </xsd:restriction>\n", typmod -
VARHDRSZ, tz);
4069 case TIMESTAMPTZOID:
4071 const char *tz = (typeoid == TIMESTAMPTZOID ?
"(\\+|-)\\p{Nd}{2}:\\p{Nd}{2}" :
"");
4075 " <xsd:restriction base=\"xsd:dateTime\">\n"
4076 " <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"
4077 " </xsd:restriction>\n", tz);
4078 else if (typmod == 0)
4080 " <xsd:restriction base=\"xsd:dateTime\">\n"
4081 " <xsd:pattern value=\"\\p{Nd}{4}-\\p{Nd}{2}-\\p{Nd}{2}T\\p{Nd}{2}:\\p{Nd}{2}:\\p{Nd}{2}%s\"/>\n"
4082 " </xsd:restriction>\n", tz);
4085 " <xsd:restriction base=\"xsd:dateTime\">\n"
4086 " <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"
4087 " </xsd:restriction>\n", typmod -
VARHDRSZ, tz);
4093 " <xsd:restriction base=\"xsd:date\">\n"
4094 " <xsd:pattern value=\"\\p{Nd}{4}-\\p{Nd}{2}-\\p{Nd}{2}\"/>\n"
4095 " </xsd:restriction>\n");
4102 int32 base_typmod = -1;
4107 " <xsd:restriction base=\"%s\"/>\n",
4125 bool nulls,
bool tableforest,
4126 const char *targetns,
bool top_level)
4198 if (
cur->type != XML_ATTRIBUTE_NODE &&
cur->type != XML_TEXT_NODE)
4200 void (*
volatile nodefree) (xmlNodePtr) = NULL;
4201 volatile xmlBufferPtr
buf = NULL;
4202 volatile xmlNodePtr cur_copy = NULL;
4208 buf = xmlBufferCreate();
4209 if (
buf == NULL || xmlerrcxt->err_occurred)
4211 "could not allocate xmlBuffer");
4225 cur_copy = xmlCopyNode(
cur, 1);
4226 if (cur_copy == NULL || xmlerrcxt->err_occurred)
4228 "could not copy node");
4229 nodefree = (cur_copy->type == XML_DOCUMENT_NODE) ?
4230 (
void (*) (xmlNodePtr)) xmlFreeDoc : xmlFreeNode;
4232 bytes = xmlNodeDump(
buf, NULL, cur_copy, 0, 0);
4233 if (bytes == -1 || xmlerrcxt->err_occurred)
4235 "could not dump node");
4237 result = xmlBuffer_to_xmltype(
buf);
4250 volatile xmlChar *
str = NULL;
4256 str = xmlXPathCastNodeToString(
cur);
4257 if (
str == NULL || xmlerrcxt->err_occurred)
4259 "could not allocate xmlChar");
4270 xmlFree((xmlChar *)
str);
4291xml_xpathobjtoxmlarray(xmlXPathObjectPtr xpathobj,
4300 switch (xpathobj->type)
4303 if (xpathobj->nodesetval != NULL)
4305 result = xpathobj->nodesetval->nodeNr;
4310 for (
i = 0;
i < result;
i++)
4312 datum =
PointerGetDatum(xml_xmlnodetoxmltype(xpathobj->nodesetval->nodeTab[
i],
4325 datumtype = BOOLOID;
4332 datumtype = FLOAT8OID;
4339 datumtype = CSTRINGOID;
4343 elog(
ERROR,
"xpath expression result type %d is unsupported",
4373 volatile xmlParserCtxtPtr ctxt = NULL;
4374 volatile xmlDocPtr doc = NULL;
4375 volatile xmlXPathContextPtr xpathctx = NULL;
4376 volatile xmlXPathCompExprPtr xpathcomp = NULL;
4377 volatile xmlXPathObjectPtr xpathobj = NULL;
4382 xmlChar *xpath_expr;
4383 size_t xmldecl_len = 0;
4386 Datum *ns_names_uris;
4387 bool *ns_names_uris_nulls;
4399 ndim = namespaces ?
ARR_NDIM(namespaces) : 0;
4406 if (ndim != 2 || dims[1] != 2)
4408 (
errcode(ERRCODE_DATA_EXCEPTION),
4409 errmsg(
"invalid array for XML namespace mapping"),
4410 errdetail(
"The array must be two-dimensional with length of the second axis equal to 2.")));
4415 &ns_names_uris, &ns_names_uris_nulls,
4418 Assert((ns_count % 2) == 0);
4423 ns_names_uris = NULL;
4424 ns_names_uris_nulls = NULL;
4433 (
errcode(ERRCODE_INVALID_ARGUMENT_FOR_XQUERY),
4434 errmsg(
"empty XPath expression")));
4436 string = pg_xmlCharStrndup(datastr,
len);
4437 xpath_expr = pg_xmlCharStrndup(
VARDATA_ANY(xpath_expr_text), xpath_len);
4447 parse_xml_decl(
string, &xmldecl_len, NULL, NULL, NULL);
4459 ctxt = xmlNewParserCtxt();
4460 if (ctxt == NULL || xmlerrcxt->err_occurred)
4462 "could not allocate parser context");
4463 doc = xmlCtxtReadMemory(ctxt, (
char *)
string + xmldecl_len,
4464 len - xmldecl_len, NULL, NULL, 0);
4465 if (doc == NULL || xmlerrcxt->err_occurred)
4467 "could not parse XML document");
4468 xpathctx = xmlXPathNewContext(doc);
4469 if (xpathctx == NULL || xmlerrcxt->err_occurred)
4471 "could not allocate XPath context");
4472 xpathctx->node = (xmlNodePtr) doc;
4477 for (
i = 0;
i < ns_count;
i++)
4482 if (ns_names_uris_nulls[
i * 2] ||
4483 ns_names_uris_nulls[
i * 2 + 1])
4485 (
errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4486 errmsg(
"neither namespace name nor URI may be null")));
4489 if (xmlXPathRegisterNs(xpathctx,
4490 (xmlChar *) ns_name,
4491 (xmlChar *) ns_uri) != 0)
4493 (
errmsg(
"could not register XML namespace with name \"%s\" and URI \"%s\"",
4504 xpathcomp = xmlXPathCtxtCompile(xpathctx, xpath_expr);
4505 if (xpathcomp == NULL || xmlerrcxt->err_occurred)
4507 "invalid XPath expression");
4516 xpathobj = xmlXPathCompiledEval(xpathcomp, xpathctx);
4517 if (xpathobj == NULL || xmlerrcxt->err_occurred)
4519 "could not create XPath object");
4524 if (res_nitems != NULL)
4525 *res_nitems = xml_xpathobjtoxmlarray(xpathobj, astate, xmlerrcxt);
4527 (
void) xml_xpathobjtoxmlarray(xpathobj, astate, xmlerrcxt);
4532 xmlXPathFreeObject(xpathobj);
4534 xmlXPathFreeCompExpr(xpathcomp);
4536 xmlXPathFreeContext(xpathctx);
4540 xmlFreeParserCtxt(ctxt);
4548 xmlXPathFreeObject(xpathobj);
4549 xmlXPathFreeCompExpr(xpathcomp);
4550 xmlXPathFreeContext(xpathctx);
4552 xmlFreeParserCtxt(ctxt);
4575 xpath_internal(xpath_expr_text,
data, namespaces,
4596 xpath_internal(xpath_expr_text,
data, NULL,
4620 xpath_internal(xpath_expr_text,
data, namespaces,
4644 doc = xml_parse(
data, xmloption_arg,
true,
4702static inline XmlTableBuilderData *
4705 XmlTableBuilderData *result;
4708 elog(
ERROR,
"%s called with invalid TableFuncScanState", fname);
4709 result = (XmlTableBuilderData *)
state->opaque;
4710 if (result->magic != XMLTABLE_CONTEXT_MAGIC)
4711 elog(
ERROR,
"%s called with invalid TableFuncScanState", fname);
4732 volatile xmlParserCtxtPtr ctxt = NULL;
4733 XmlTableBuilderData *xtCxt;
4736 xtCxt =
palloc0(
sizeof(XmlTableBuilderData));
4737 xtCxt->magic = XMLTABLE_CONTEXT_MAGIC;
4738 xtCxt->natts = natts;
4739 xtCxt->xpathscomp =
palloc0(
sizeof(xmlXPathCompExprPtr) * natts);
4747 ctxt = xmlNewParserCtxt();
4748 if (ctxt == NULL || xmlerrcxt->err_occurred)
4750 "could not allocate parser context");
4755 xmlFreeParserCtxt(ctxt);
4763 xtCxt->xmlerrcxt = xmlerrcxt;
4766 state->opaque = xtCxt;
4780 XmlTableBuilderData *xtCxt;
4785 volatile xmlDocPtr doc = NULL;
4786 volatile xmlXPathContextPtr xpathcxt = NULL;
4788 xtCxt = GetXmlTableBuilderPrivateData(
state,
"XmlTableSetDocument");
4796 length = strlen(
str);
4797 xstr = pg_xmlCharStrndup(
str, length);
4801 doc = xmlCtxtReadMemory(xtCxt->ctxt, (
char *) xstr, length, NULL, NULL, 0);
4802 if (doc == NULL || xtCxt->xmlerrcxt->err_occurred)
4804 "could not parse XML document");
4805 xpathcxt = xmlXPathNewContext(doc);
4806 if (xpathcxt == NULL || xtCxt->xmlerrcxt->err_occurred)
4808 "could not allocate XPath context");
4809 xpathcxt->node = (xmlNodePtr) doc;
4813 if (xpathcxt != NULL)
4814 xmlXPathFreeContext(xpathcxt);
4823 xtCxt->xpathcxt = xpathcxt;
4837 XmlTableBuilderData *xtCxt;
4841 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4842 errmsg(
"DEFAULT namespace is not supported")));
4843 xtCxt = GetXmlTableBuilderPrivateData(
state,
"XmlTableSetNamespace");
4845 if (xmlXPathRegisterNs(xtCxt->xpathcxt,
4846 pg_xmlCharStrndup(
name, strlen(
name)),
4847 pg_xmlCharStrndup(uri, strlen(uri))))
4849 "could not set XML namespace");
4863 XmlTableBuilderData *xtCxt;
4866 xtCxt = GetXmlTableBuilderPrivateData(
state,
"XmlTableSetRowFilter");
4870 (
errcode(ERRCODE_INVALID_ARGUMENT_FOR_XQUERY),
4871 errmsg(
"row path filter must not be empty string")));
4873 xstr = pg_xmlCharStrndup(path, strlen(path));
4876 Assert(xtCxt->xpathcxt != NULL);
4878 xtCxt->xpathcomp = xmlXPathCtxtCompile(xtCxt->xpathcxt, xstr);
4879 if (xtCxt->xpathcomp == NULL || xtCxt->xmlerrcxt->err_occurred)
4881 "invalid XPath expression");
4895 XmlTableBuilderData *xtCxt;
4900 xtCxt = GetXmlTableBuilderPrivateData(
state,
"XmlTableSetColumnFilter");
4904 (
errcode(ERRCODE_INVALID_ARGUMENT_FOR_XQUERY),
4905 errmsg(
"column path filter must not be empty string")));
4907 xstr = pg_xmlCharStrndup(path, strlen(path));
4910 Assert(xtCxt->xpathcxt != NULL);
4912 xtCxt->xpathscomp[colnum] = xmlXPathCtxtCompile(xtCxt->xpathcxt, xstr);
4913 if (xtCxt->xpathscomp[colnum] == NULL || xtCxt->xmlerrcxt->err_occurred)
4915 "invalid XPath expression");
4930 XmlTableBuilderData *xtCxt;
4932 xtCxt = GetXmlTableBuilderPrivateData(
state,
"XmlTableFetchRow");
4935 xmlSetStructuredErrorFunc(xtCxt->xmlerrcxt, xml_errorHandler);
4937 if (xtCxt->xpathobj == NULL)
4939 xtCxt->xpathobj = xmlXPathCompiledEval(xtCxt->xpathcomp, xtCxt->xpathcxt);
4940 if (xtCxt->xpathobj == NULL || xtCxt->xmlerrcxt->err_occurred)
4942 "could not create XPath object");
4944 xtCxt->row_count = 0;
4947 if (xtCxt->xpathobj->type == XPATH_NODESET)
4949 if (xtCxt->xpathobj->nodesetval != NULL)
4951 if (xtCxt->row_count++ < xtCxt->xpathobj->nodesetval->nodeNr)
4973 Oid typid,
int32 typmod,
bool *isnull)
4977 XmlTableBuilderData *xtCxt;
4978 volatile xmlXPathObjectPtr xpathobj = NULL;
4980 xtCxt = GetXmlTableBuilderPrivateData(
state,
"XmlTableGetValue");
4982 Assert(xtCxt->xpathobj &&
4983 xtCxt->xpathobj->type == XPATH_NODESET &&
4984 xtCxt->xpathobj->nodesetval != NULL);
4987 xmlSetStructuredErrorFunc(xtCxt->xmlerrcxt, xml_errorHandler);
4991 Assert(xtCxt->xpathscomp[colnum] != NULL);
4999 cur = xtCxt->xpathobj->nodesetval->nodeTab[xtCxt->row_count - 1];
5000 xtCxt->xpathcxt->node =
cur;
5003 xpathobj = xmlXPathCompiledEval(xtCxt->xpathscomp[colnum], xtCxt->xpathcxt);
5004 if (xpathobj == NULL || xtCxt->xmlerrcxt->err_occurred)
5006 "could not create XPath object");
5015 if (xpathobj->type == XPATH_NODESET)
5019 if (xpathobj->nodesetval != NULL)
5020 count = xpathobj->nodesetval->nodeNr;
5022 if (xpathobj->nodesetval == NULL || count == 0)
5028 if (typid == XMLOID)
5035 for (
int i = 0;
i < count;
i++)
5038 xml_xmlnodetoxmltype(xpathobj->nodesetval->nodeTab[
i],
5051 (
errcode(ERRCODE_CARDINALITY_VIOLATION),
5052 errmsg(
"more than one value returned by column XPath expression")));
5054 str = xmlXPathCastNodeSetToString(xpathobj->nodesetval);
5055 cstr =
str ? xml_pstrdup_and_free(
str) :
"";
5059 else if (xpathobj->type == XPATH_STRING)
5062 if (typid == XMLOID)
5063 cstr =
escape_xml((
char *) xpathobj->stringval);
5065 cstr = (
char *) xpathobj->stringval;
5067 else if (xpathobj->type == XPATH_BOOLEAN)
5070 bool typispreferred;
5076 if (typcategory != TYPCATEGORY_NUMERIC)
5077 str = xmlXPathCastBooleanToString(xpathobj->boolval);
5079 str = xmlXPathCastNumberToString(xmlXPathCastBooleanToNumber(xpathobj->boolval));
5081 cstr = xml_pstrdup_and_free(
str);
5083 else if (xpathobj->type == XPATH_NUMBER)
5087 str = xmlXPathCastNumberToString(xpathobj->floatval);
5088 cstr = xml_pstrdup_and_free(
str);
5091 elog(
ERROR,
"unexpected XPath object type %u", xpathobj->type);
5102 state->typioparams[colnum],
5107 if (xpathobj != NULL)
5108 xmlXPathFreeObject(xpathobj);
5127 XmlTableBuilderData *xtCxt;
5129 xtCxt = GetXmlTableBuilderPrivateData(
state,
"XmlTableDestroyOpaque");
5132 xmlSetStructuredErrorFunc(xtCxt->xmlerrcxt, xml_errorHandler);
5134 if (xtCxt->xpathscomp != NULL)
5138 for (
i = 0;
i < xtCxt->natts;
i++)
5139 if (xtCxt->xpathscomp[
i] != NULL)
5140 xmlXPathFreeCompExpr(xtCxt->xpathscomp[
i]);
5143 if (xtCxt->xpathobj != NULL)
5144 xmlXPathFreeObject(xtCxt->xpathobj);
5145 if (xtCxt->xpathcomp != NULL)
5146 xmlXPathFreeCompExpr(xtCxt->xpathcomp);
5147 if (xtCxt->xpathcxt != NULL)
5148 xmlXPathFreeContext(xtCxt->xpathcxt);
5149 if (xtCxt->doc != NULL)
5150 xmlFreeDoc(xtCxt->doc);
5151 if (xtCxt->ctxt != NULL)
5152 xmlFreeParserCtxt(xtCxt->ctxt);
5158 state->opaque = NULL;
#define PG_GETARG_ARRAYTYPE_P(n)
#define DatumGetArrayTypeP(X)
ArrayBuildState * accumArrayResult(ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
void deconstruct_array_builtin(ArrayType *array, Oid elmtype, Datum **elemsp, bool **nullsp, int *nelemsp)
ArrayBuildState * initArrayResult(Oid element_type, MemoryContext rcontext, bool subcontext)
Datum makeArrayResult(ArrayBuildState *astate, MemoryContext rcontext)
void j2date(int jd, int *year, int *month, int *day)
void EncodeDateTime(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, const char *tzn, int style, char *str)
void EncodeDateOnly(struct pg_tm *tm, int style, char *str)
int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
#define TextDatumGetCString(d)
#define OidIsValid(objectId)
#define TIMESTAMP_NOT_FINITE(j)
#define POSTGRES_EPOCH_JDATE
#define DATE_NOT_FINITE(j)
static DateADT DatumGetDateADT(Datum X)
int errmsg_internal(const char *fmt,...)
int errdetail_internal(const char *fmt,...)
int errdetail(const char *fmt,...)
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define errsave(context,...)
#define ereport(elevel,...)
Datum InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod)
char * OidOutputFunctionCall(Oid functionId, Datum val)
#define PG_GETARG_TEXT_PP(n)
#define PG_RETURN_BYTEA_P(x)
#define DatumGetByteaPP(X)
#define PG_GETARG_POINTER(n)
#define PG_RETURN_CSTRING(x)
#define DirectFunctionCall1(func, arg1)
#define PG_GETARG_CSTRING(n)
#define PG_GETARG_NAME(n)
#define PG_RETURN_TEXT_P(x)
#define PG_GETARG_INT32(n)
#define PG_GETARG_BOOL(n)
#define PG_RETURN_DATUM(x)
#define PG_RETURN_BOOL(x)
Assert(PointerIsAligned(start, uint64))
#define HeapTupleIsValid(tuple)
static void * GETSTRUCT(const HeapTupleData *tuple)
if(TABLE==NULL||TABLE_index==NULL)
List * lappend(List *list, void *datum)
List * lappend_oid(List *list, Oid datum)
List * list_append_unique_oid(List *list, Oid datum)
char * get_rel_name(Oid relid)
char * get_database_name(Oid dbid)
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
char get_typtype(Oid typid)
Oid getBaseTypeAndTypmod(Oid typid, int32 *typmod)
Oid getBaseType(Oid typid)
char * get_namespace_name(Oid nspid)
void get_type_category_preferred(Oid typid, char *typcategory, bool *typispreferred)
#define type_is_array_domain(typid)
int GetDatabaseEncoding(void)
char * pg_any_to_server(const char *s, int len, int encoding)
unsigned char * pg_do_encoding_conversion(unsigned char *src, int len, int src_encoding, int dest_encoding)
void pg_unicode_to_server(pg_wchar c, unsigned char *s)
int pg_get_client_encoding(void)
char * pg_server_to_any(const char *s, int len, int encoding)
int pg_encoding_mb2wchar_with_len(int encoding, const char *from, pg_wchar *to, int len)
int pg_mblen(const char *mbstr)
char * MemoryContextStrdup(MemoryContext context, const char *string)
void * MemoryContextAlloc(MemoryContext context, Size size)
char * pstrdup(const char *in)
void * repalloc(void *pointer, Size size)
void pfree(void *pointer)
void * palloc0(Size size)
MemoryContext TopMemoryContext
MemoryContext CurrentMemoryContext
#define AllocSetContextCreate
#define ALLOCSET_DEFAULT_SIZES
Oid LookupExplicitNamespace(const char *nspname, bool missing_ok)
Oid exprType(const Node *expr)
#define IsA(nodeptr, _type_)
FormData_pg_attribute * Form_pg_attribute
#define ERRCODE_DATA_CORRUPTED
FormData_pg_class * Form_pg_class
#define forboth(cell1, list1, cell2, list2)
#define list_make2(x1, x2)
FormData_pg_type * Form_pg_type
#define MAX_MULTIBYTE_CHAR_LEN
#define MAX_UNICODE_EQUIVALENT_STRING
#define pg_encoding_to_char
#define pg_char_to_encoding
int pg_strcasecmp(const char *s1, const char *s2)
size_t strnlen(const char *str, size_t maxlen)
int pg_strncasecmp(const char *s1, const char *s2, size_t n)
static bool DatumGetBool(Datum X)
static Datum PointerGetDatum(const void *X)
static Oid DatumGetObjectId(Datum X)
static Datum BoolGetDatum(bool X)
static Datum ObjectIdGetDatum(Oid X)
static char * DatumGetCString(Datum X)
static Datum Float8GetDatum(float8 X)
static Datum CStringGetDatum(const char *X)
Datum regclassout(PG_FUNCTION_ARGS)
Oid SPI_gettypeid(TupleDesc tupdesc, int fnumber)
const char * SPI_result_code_string(int code)
SPITupleTable * SPI_tuptable
Portal SPI_cursor_find(const char *name)
void SPI_cursor_fetch(Portal portal, bool forward, long count)
Portal SPI_cursor_open(const char *name, SPIPlanPtr plan, Datum *Values, const char *Nulls, bool read_only)
SPIPlanPtr SPI_prepare(const char *src, int nargs, Oid *argtypes)
void SPI_cursor_close(Portal portal)
void * SPI_palloc(Size size)
int SPI_execute(const char *src, bool read_only, long tcount)
Datum SPI_getbinval(HeapTuple tuple, TupleDesc tupdesc, int fnumber, bool *isnull)
char * SPI_fname(TupleDesc tupdesc, int fnumber)
struct StringInfoData * StringInfo
void destroyStringInfo(StringInfo str)
StringInfo makeStringInfo(void)
void appendStringInfo(StringInfo str, const char *fmt,...)
void appendBinaryStringInfo(StringInfo str, const void *data, int datalen)
void appendStringInfoString(StringInfo str, const char *s)
void appendStringInfoChar(StringInfo str, char ch)
void initStringInfo(StringInfo str)
#define appendStringInfoCharMacro(str, ch)
void(* InitOpaque)(TableFuncScanState *state, int natts)
void ReleaseSysCache(HeapTuple tuple)
HeapTuple SearchSysCache1(int cacheId, Datum key1)
void table_close(Relation relation, LOCKMODE lockmode)
Relation table_open(Oid relationId, LOCKMODE lockmode)
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
struct TupleDescData * TupleDesc
static Timestamp DatumGetTimestamp(Datum X)
static Size VARSIZE_ANY_EXHDR(const void *PTR)
static Size VARSIZE(const void *PTR)
static char * VARDATA(const void *PTR)
static char * VARDATA_ANY(const void *PTR)
static void SET_VARSIZE(void *PTR, Size len)
static void appendStringInfoText(StringInfo str, const text *t)
text * cstring_to_text_with_len(const char *s, int len)
text * cstring_to_text(const char *s)
char * text_to_cstring(const text *t)
int pg_encoding_mblen(int encoding, const char *mbstr)
Datum xml_in(PG_FUNCTION_ARGS)
Datum cursor_to_xmlschema(PG_FUNCTION_ARGS)
Datum table_to_xml(PG_FUNCTION_ARGS)
Datum query_to_xmlschema(PG_FUNCTION_ARGS)
Datum database_to_xml(PG_FUNCTION_ARGS)
static const char * map_sql_catalog_to_xmlschema_types(List *nspid_list, bool nulls, bool tableforest, const char *targetns)
xmltype * xmlroot(xmltype *data, text *version, int standalone)
static void XmlTableInitOpaque(struct TableFuncScanState *state, int natts)
static const char * map_sql_type_to_xml_name(Oid typeoid, int typmod)
static const char * map_sql_type_to_xmlschema_type(Oid typeoid, int typmod)
Datum texttoxml(PG_FUNCTION_ARGS)
static char * xml_out_internal(xmltype *x, pg_enc target_encoding)
char * map_sql_identifier_to_xml_name(const char *ident, bool fully_escaped, bool escape_period)
static void xsd_schema_element_start(StringInfo result, const char *targetns)
Datum query_to_xml_and_xmlschema(PG_FUNCTION_ARGS)
Datum xmltotext(PG_FUNCTION_ARGS)
Datum schema_to_xml_and_xmlschema(PG_FUNCTION_ARGS)
Datum xmlexists(PG_FUNCTION_ARGS)
Datum xmltext(PG_FUNCTION_ARGS)
static char * map_multipart_sql_identifier_to_xml_name(const char *a, const char *b, const char *c, const char *d)
static StringInfo database_to_xmlschema_internal(bool nulls, bool tableforest, const char *targetns)
Datum database_to_xmlschema(PG_FUNCTION_ARGS)
static List * schema_get_xml_visible_tables(Oid nspid)
Datum schema_to_xmlschema(PG_FUNCTION_ARGS)
text * xmltotext_with_options(xmltype *data, XmlOptionType xmloption_arg, bool indent)
static void xmldata_root_element_start(StringInfo result, const char *eltname, const char *xmlschema, const char *targetns, bool top_level)
char * map_sql_value_to_xml_value(Datum value, Oid type, bool xml_escape_strings)
Datum xml_send(PG_FUNCTION_ARGS)
static const char * map_sql_schema_to_xmlschema_types(Oid nspid, List *relid_list, bool nulls, bool tableforest, const char *targetns)
const TableFuncRoutine XmlTableRoutine
Datum xmlcomment(PG_FUNCTION_ARGS)
static void XmlTableSetNamespace(struct TableFuncScanState *state, const char *name, const char *uri)
Datum xmlconcat2(PG_FUNCTION_ARGS)
static void XmlTableSetRowFilter(struct TableFuncScanState *state, const char *path)
static List * database_get_xml_visible_schemas(void)
static void xmldata_root_element_end(StringInfo result, const char *eltname)
xmltype * xmlconcat(List *args)
static Datum XmlTableGetValue(struct TableFuncScanState *state, int colnum, Oid typid, int32 typmod, bool *isnull)
char * escape_xml(const char *str)
Datum xml_is_well_formed_document(PG_FUNCTION_ARGS)
Datum query_to_xml(PG_FUNCTION_ARGS)
static StringInfo database_to_xml_internal(const char *xmlschema, bool nulls, bool tableforest, const char *targetns)
static xmltype * stringinfo_to_xmltype(StringInfo buf)
Datum xml_is_well_formed_content(PG_FUNCTION_ARGS)
#define XML_VISIBLE_SCHEMAS
static List * database_get_xml_visible_tables(void)
bool xml_is_document(xmltype *arg)
static StringInfo schema_to_xmlschema_internal(const char *schemaname, bool nulls, bool tableforest, const char *targetns)
Datum table_to_xml_and_xmlschema(PG_FUNCTION_ARGS)
Datum xmlvalidate(PG_FUNCTION_ARGS)
xmltype * xmlparse(text *data, XmlOptionType xmloption_arg, bool preserve_whitespace)
static xmltype * cstring_to_xmltype(const char *string)
static List * query_to_oid_list(const char *query)
xmltype * xmlelement(XmlExpr *xexpr, Datum *named_argvalue, bool *named_argnull, Datum *argvalue, bool *argnull)
static void XmlTableSetDocument(struct TableFuncScanState *state, Datum value)
static void XmlTableDestroyOpaque(struct TableFuncScanState *state)
static const char * map_sql_typecoll_to_xmlschema_types(List *tupdesc_list)
#define PG_XML_DEFAULT_VERSION
Datum table_to_xmlschema(PG_FUNCTION_ARGS)
static StringInfo query_to_xml_internal(const char *query, char *tablename, const char *xmlschema, bool nulls, bool tableforest, const char *targetns, bool top_level)
static void SPI_sql_row_to_xmlelement(uint64 rownum, StringInfo result, char *tablename, bool nulls, bool tableforest, const char *targetns, bool top_level)
static StringInfo schema_to_xml_internal(Oid nspid, const char *xmlschema, bool nulls, bool tableforest, const char *targetns, bool top_level)
static StringInfo table_to_xml_internal(Oid relid, const char *xmlschema, bool nulls, bool tableforest, const char *targetns, bool top_level)
Datum schema_to_xml(PG_FUNCTION_ARGS)
char * map_xml_name_to_sql_identifier(const char *name)
Datum database_to_xml_and_xmlschema(PG_FUNCTION_ARGS)
static bool XmlTableFetchRow(struct TableFuncScanState *state)
Datum cursor_to_xml(PG_FUNCTION_ARGS)
Datum xpath_exists(PG_FUNCTION_ARGS)
Datum xml_is_well_formed(PG_FUNCTION_ARGS)
static char * _SPI_strdup(const char *s)
static void XmlTableSetColumnFilter(struct TableFuncScanState *state, const char *path, int colnum)
static const char * map_sql_table_to_xmlschema(TupleDesc tupdesc, Oid relid, bool nulls, bool tableforest, const char *targetns)
Datum xml_out(PG_FUNCTION_ARGS)
Datum xml_recv(PG_FUNCTION_ARGS)
xmltype * xmlpi(const char *target, text *arg, bool arg_is_null, bool *result_is_null)
Datum xpath(PG_FUNCTION_ARGS)
static void xsd_schema_element_end(StringInfo result)
@ XML_STANDALONE_NO_VALUE
struct PgXmlErrorContext PgXmlErrorContext
PgXmlErrorContext * pg_xml_init(PgXmlStrictness strictness)
#define PG_RETURN_XML_P(x)
void xml_ereport(PgXmlErrorContext *errcxt, int level, int sqlcode, const char *msg)
bool pg_xml_error_occurred(PgXmlErrorContext *errcxt)
static xmltype * DatumGetXmlP(Datum X)
void pg_xml_done(PgXmlErrorContext *errcxt, bool isError)
#define PG_GETARG_XML_P(n)
void pg_xml_init_library(void)
@ PG_XML_STRICTNESS_LEGACY
@ PG_XML_STRICTNESS_WELLFORMED