77 * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
88 * Portions Copyright (c) 1994, Regents of the University of California
99 *
10- * $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.96 2010/02/14 18:42:17 rhaas Exp $
10+ * $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.97 2010/03/03 17:29:45 tgl Exp $
1111 *
1212 *-------------------------------------------------------------------------
1313 */
@@ -86,7 +86,6 @@ intxmloption;
8686
8787static StringInfo xml_err_buf = NULL ;
8888
89- static void xml_ereport (int level ,int sqlcode ,const char * msg );
9089static void xml_errorHandler (void * ctxt ,const char * msg ,...);
9190static void xml_ereport_by_code (int level ,int sqlcode ,
9291const char * msg ,int errcode );
@@ -102,7 +101,6 @@ static void xml_pfree(void *ptr);
102101static char * xml_pstrdup (const char * string );
103102#endif /* USE_LIBXMLCONTEXT */
104103
105- static void xml_init (void );
106104static xmlChar * xml_text2xmlChar (text * in );
107105static int parse_xml_decl (const xmlChar * str ,size_t * lenp ,
108106xmlChar * * version ,xmlChar * * encoding ,int * standalone );
@@ -599,7 +597,7 @@ xmlelement(XmlExprState *xmlExpr, ExprContext *econtext)
599597}
600598
601599/* now safe to run libxml */
602- xml_init ();
600+ pg_xml_init ();
603601
604602PG_TRY ();
605603{
@@ -845,14 +843,23 @@ xml_is_document(xmltype *arg)
845843#ifdef USE_LIBXML
846844
847845/*
848- * Set up for use of libxml --- this should be called by each function that
849- * is about to use libxml facilities.
846+ * pg_xml_init --- set up for use of libxml
847+ *
848+ * This should be called by each function that is about to use libxml
849+ * facilities. It has two responsibilities: verify compatibility with the
850+ * loaded libxml version (done on first call in a session) and establish
851+ * or re-establish our libxml error handler. The latter needs to be done
852+ * anytime we might have passed control to add-on modules (eg libperl) which
853+ * might have set their own error handler for libxml.
854+ *
855+ * This is exported for use by contrib/xml2, as well as other code that might
856+ * wish to share use of this module's libxml error handler.
850857 *
851858 * TODO: xmlChar is utf8-char, make proper tuning (initdb with enc!=utf8 and
852859 * check)
853860 */
854- static void
855- xml_init (void )
861+ void
862+ pg_xml_init (void )
856863{
857864static bool first_time = true;
858865
@@ -962,7 +969,7 @@ parse_xml_decl(const xmlChar *str, size_t *lenp,
962969int utf8char ;
963970int utf8len ;
964971
965- xml_init ();
972+ pg_xml_init ();
966973
967974/* Initialize output arguments to "not present" */
968975if (version )
@@ -1114,7 +1121,7 @@ static bool
11141121print_xml_decl (StringInfo buf ,const xmlChar * version ,
11151122pg_enc encoding ,int standalone )
11161123{
1117- xml_init ();/* why is this here? */
1124+ pg_xml_init ();/* why is this here? */
11181125
11191126if ((version && strcmp ((char * )version ,PG_XML_DEFAULT_VERSION )!= 0 )
11201127|| (encoding && encoding != PG_UTF8 )
@@ -1178,7 +1185,7 @@ xml_parse(text *data, XmlOptionType xmloption_arg, bool preserve_whitespace,
11781185PG_UTF8 );
11791186
11801187/* Start up libxml and its parser (no-ops if already done) */
1181- xml_init ();
1188+ pg_xml_init ();
11821189xmlInitParser ();
11831190
11841191ctxt = xmlNewParserCtxt ();
@@ -1314,16 +1321,26 @@ xml_pstrdup(const char *string)
13141321
13151322
13161323/*
1317- * Wrapper for "ereport" function for XML-related errors. The "msg"
1318- * is the SQL-level message; some can be adopted from the SQL/XML
1319- * standard. This function adds libxml's native error messages, if
1320- * any, as detail.
1324+ * xml_ereport --- report an XML-related error
1325+ *
1326+ * The "msg" is the SQL-level message; some can be adopted from the SQL/XML
1327+ * standard. This function adds libxml's native error message, if any, as
1328+ * detail.
1329+ *
1330+ * This is exported for modules that want to share the core libxml error
1331+ * handler. Note that pg_xml_init() *must* have been called previously.
13211332 */
1322- static void
1333+ void
13231334xml_ereport (int level ,int sqlcode ,const char * msg )
13241335{
13251336char * detail ;
13261337
1338+ /*
1339+ * It might seem that we should just pass xml_err_buf->data directly to
1340+ * errdetail. However, we want to clean out xml_err_buf before throwing
1341+ * error, in case there is another function using libxml further down
1342+ * the call stack.
1343+ */
13271344if (xml_err_buf -> len > 0 )
13281345{
13291346detail = pstrdup (xml_err_buf -> data );
@@ -1332,11 +1349,11 @@ xml_ereport(int level, int sqlcode, const char *msg)
13321349else
13331350detail = NULL ;
13341351
1335- /* libxml error messages end in '\n'; get rid of it */
13361352if (detail )
13371353{
13381354size_t len ;
13391355
1356+ /* libxml error messages end in '\n'; get rid of it */
13401357len = strlen (detail );
13411358if (len > 0 && detail [len - 1 ]== '\n' )
13421359detail [len - 1 ]= '\0' ;
@@ -1738,7 +1755,7 @@ map_sql_value_to_xml_value(Datum value, Oid type, bool xml_escape_strings)
17381755xmlTextWriterPtr writer = NULL ;
17391756char * result ;
17401757
1741- xml_init ();
1758+ pg_xml_init ();
17421759
17431760PG_TRY ();
17441761{
@@ -3367,7 +3384,7 @@ xpath(PG_FUNCTION_ARGS)
33673384memcpy (xpath_expr ,VARDATA (xpath_expr_text ),xpath_len );
33683385xpath_expr [xpath_len ]= '\0' ;
33693386
3370- xml_init ();
3387+ pg_xml_init ();
33713388xmlInitParser ();
33723389
33733390PG_TRY ();