From d6a6f8c6be4b6d6a9e90e92d91a83225bfe8d29d Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Mon, 1 Mar 2010 18:07:59 +0000
Subject: [PATCH] Fix contrib/xml2 so regression test still works when it's
 built without libxslt.

This involves modifying the module to have a stable ABI, that is, the
xslt_process() function still exists even without libxslt.  It throws a
runtime error if called, but doesn't prevent executing the CREATE FUNCTION
call.  This is a good thing anyway to simplify cross-version upgrades.
---
 contrib/xml2/Makefile            |   4 +-
 contrib/xml2/expected/xml2_1.out | 109 +++++++++++++++++++++++++++++++
 contrib/xml2/pgxml.sql.in        |  11 +---
 contrib/xml2/xslt_proc.c         |  24 ++++++-
 4 files changed, 135 insertions(+), 13 deletions(-)
 create mode 100644 contrib/xml2/expected/xml2_1.out

diff --git a/contrib/xml2/Makefile b/contrib/xml2/Makefile
index 3426deaa25d..dd45a914c93 100644
--- a/contrib/xml2/Makefile
+++ b/contrib/xml2/Makefile
@@ -1,8 +1,8 @@
-# $PostgreSQL: pgsql/contrib/xml2/Makefile,v 1.13 2010/02/28 21:31:57 tgl Exp $
+# $PostgreSQL: pgsql/contrib/xml2/Makefile,v 1.14 2010/03/01 18:07:59 tgl Exp $
 
 MODULE_big = pgxml
 
-OBJS = $(if $(filter -lxslt, $(LIBS)), xpath.o xslt_proc.o, xpath.o)
+OBJS = xpath.o xslt_proc.o
 
 SHLIB_LINK += $(filter -lxslt, $(LIBS)) $(filter -lxml2, $(LIBS))
 
diff --git a/contrib/xml2/expected/xml2_1.out b/contrib/xml2/expected/xml2_1.out
new file mode 100644
index 00000000000..083fc3b2cac
--- /dev/null
+++ b/contrib/xml2/expected/xml2_1.out
@@ -0,0 +1,109 @@
+--
+-- first, define the functions.  Turn off echoing so that expected file
+-- does not depend on contents of pgxml.sql.
+--
+SET client_min_messages = warning;
+\set ECHO none
+RESET client_min_messages;
+select query_to_xml('select 1 as x',true,false,'');
+                         query_to_xml                          
+---------------------------------------------------------------
+ <table xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">+
+                                                              +
+ <row>                                                        +
+   <x>1</x>                                                   +
+ </row>                                                       +
+                                                              +
+ </table>                                                     +
+ 
+(1 row)
+
+select xslt_process( query_to_xml('select x from generate_series(1,5) as 
+x',true,false,'')::text,
+$$<xsl:stylesheet version="1.0"
+               xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:output method="xml" indent="yes" />
+<xsl:template match="*">
+  <xsl:copy>
+     <xsl:copy-of select="@*" />
+     <xsl:apply-templates />
+  </xsl:copy>
+</xsl:template>
+<xsl:template match="comment()|processing-instruction()">
+  <xsl:copy />
+</xsl:template>
+</xsl:stylesheet>
+$$::text);
+ERROR:  xslt_process() is not available without libxslt
+CREATE TABLE xpath_test (id integer NOT NULL, t xml);
+INSERT INTO xpath_test VALUES (1, '<doc><int>1</int></doc>');
+SELECT * FROM xpath_table('id', 't', 'xpath_test', '/doc/int', 'true')
+as t(id int4);
+ id 
+----
+(0 rows)
+
+SELECT * FROM xpath_table('id', 't', 'xpath_test', '/doc/int', 'true')
+as t(id int4, doc int4);
+ id | doc 
+----+-----
+  1 |   1
+(1 row)
+
+DROP TABLE xpath_test;
+CREATE TABLE xpath_test (id integer NOT NULL, t text);
+INSERT INTO xpath_test VALUES (1, '<doc><int>1</int></doc>');
+SELECT * FROM xpath_table('id', 't', 'xpath_test', '/doc/int', 'true')
+as t(id int4);
+ id 
+----
+(0 rows)
+
+SELECT * FROM xpath_table('id', 't', 'xpath_test', '/doc/int', 'true')
+as t(id int4, doc int4);
+ id | doc 
+----+-----
+  1 |   1
+(1 row)
+
+create table articles (article_id integer, article_xml xml, date_entered date);
+insert into articles (article_id, article_xml, date_entered)
+values (2, '<article><author>test</author><pages>37</pages></article>', now());
+SELECT * FROM
+xpath_table('article_id',
+            'article_xml',
+            'articles',
+            '/article/author|/article/pages|/article/title',
+            'date_entered > ''2003-01-01'' ')
+AS t(article_id integer, author text, page_count integer, title text);
+ article_id | author | page_count | title 
+------------+--------+------------+-------
+          2 | test   |         37 | 
+(1 row)
+
+-- this used to fail when invoked a second time
+select xslt_process('<aaa/>',$$<xsl:stylesheet version="1.0"
+xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:template match="@*|node()">
+      <xsl:copy>
+         <xsl:apply-templates select="@*|node()"/>
+      </xsl:copy>
+   </xsl:template>
+</xsl:stylesheet>$$)::xml;
+ERROR:  xslt_process() is not available without libxslt
+select xslt_process('<aaa/>',$$<xsl:stylesheet version="1.0"
+xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:template match="@*|node()">
+      <xsl:copy>
+         <xsl:apply-templates select="@*|node()"/>
+      </xsl:copy>
+   </xsl:template>
+</xsl:stylesheet>$$)::xml;
+ERROR:  xslt_process() is not available without libxslt
+create table t1 (id integer, xml_data xml);
+insert into t1 (id, xml_data)
+values
+(1, '<attributes><attribute name="attr_1">Some
+Value</attribute></attributes>');
+create index idx_xpath on t1 ( xpath_string
+('/attributes/attribute[@name="attr_1"]/text()', xml_data::text));
diff --git a/contrib/xml2/pgxml.sql.in b/contrib/xml2/pgxml.sql.in
index 09957d6ce09..98d8f81b575 100644
--- a/contrib/xml2/pgxml.sql.in
+++ b/contrib/xml2/pgxml.sql.in
@@ -1,4 +1,4 @@
-/* $PostgreSQL: pgsql/contrib/xml2/pgxml.sql.in,v 1.11 2007/11/13 04:24:29 momjian Exp $ */
+/* $PostgreSQL: pgsql/contrib/xml2/pgxml.sql.in,v 1.12 2010/03/01 18:07:59 tgl Exp $ */
 
 -- Adjust this setting to control where the objects get created.
 SET search_path = public;
@@ -40,22 +40,17 @@ CREATE OR REPLACE FUNCTION xpath_list(text,text,text) RETURNS text
 AS 'MODULE_PATHNAME'
 LANGUAGE C STRICT IMMUTABLE;
 
-
 CREATE OR REPLACE FUNCTION xpath_list(text,text) RETURNS text
 AS 'SELECT xpath_list($1,$2,'','')'
 LANGUAGE SQL STRICT IMMUTABLE;
 
-
-
 -- Wrapper functions for nodeset where no tags needed
 
-
 CREATE OR REPLACE FUNCTION xpath_nodeset(text,text)
 RETURNS text
 AS 'SELECT xpath_nodeset($1,$2,'''','''')'
 LANGUAGE SQL STRICT IMMUTABLE;
 
-
 CREATE OR REPLACE FUNCTION xpath_nodeset(text,text,text)
 RETURNS text
 AS 'SELECT xpath_nodeset($1,$2,'''',$3)'
@@ -69,9 +64,6 @@ AS 'MODULE_PATHNAME'
 LANGUAGE C STRICT STABLE;
 
 -- XSLT functions
--- Delete from here to the end of the file if you are not compiling with
--- XSLT support.
-
 
 CREATE OR REPLACE FUNCTION xslt_process(text,text,text)
 RETURNS text
@@ -79,7 +71,6 @@ AS 'MODULE_PATHNAME'
 LANGUAGE C STRICT VOLATILE;
 
 -- the function checks for the correct argument count
-
 CREATE OR REPLACE FUNCTION xslt_process(text,text)
 RETURNS text
 AS 'MODULE_PATHNAME'
diff --git a/contrib/xml2/xslt_proc.c b/contrib/xml2/xslt_proc.c
index 4265a561164..9b71766fceb 100644
--- a/contrib/xml2/xslt_proc.c
+++ b/contrib/xml2/xslt_proc.c
@@ -1,5 +1,5 @@
 /*
- * $PostgreSQL: pgsql/contrib/xml2/xslt_proc.c,v 1.18 2010/03/01 05:16:35 tgl Exp $
+ * $PostgreSQL: pgsql/contrib/xml2/xslt_proc.c,v 1.19 2010/03/01 18:07:59 tgl Exp $
  *
  * XSLT processing functions (requiring libxslt)
  *
@@ -13,6 +13,8 @@
 #include "miscadmin.h"
 #include "utils/builtins.h"
 
+#ifdef USE_LIBXSLT
+
 /* libxml includes */
 
 #include <libxml/xpath.h>
@@ -26,11 +28,15 @@
 #include <libxslt/transform.h>
 #include <libxslt/xsltutils.h>
 
+#endif /* USE_LIBXSLT */
+
 
 /* externally accessible functions */
 
 Datum		xslt_process(PG_FUNCTION_ARGS);
 
+#ifdef USE_LIBXSLT
+
 /* declarations to come from xpath.c */
 extern void elog_error(const char *explain, bool force);
 extern void pgxml_parser_init(void);
@@ -40,12 +46,16 @@ static void parse_params(const char **params, text *paramstr);
 
 #define MAXPARAMS 20			/* must be even, see parse_params() */
 
+#endif /* USE_LIBXSLT */
+
 
 PG_FUNCTION_INFO_V1(xslt_process);
 
 Datum
 xslt_process(PG_FUNCTION_ARGS)
 {
+#ifdef USE_LIBXSLT
+
 	text	   *doct = PG_GETARG_TEXT_P(0);
 	text	   *ssheet = PG_GETARG_TEXT_P(1);
 	text	   *paramstr;
@@ -123,8 +133,18 @@ xslt_process(PG_FUNCTION_ARGS)
 		PG_RETURN_NULL();
 
 	PG_RETURN_TEXT_P(cstring_to_text_with_len((char *) resstr, reslen));
+
+#else /* !USE_LIBXSLT */
+
+	ereport(ERROR,
+			(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+			 errmsg("xslt_process() is not available without libxslt")));
+	PG_RETURN_NULL();
+
+#endif /* USE_LIBXSLT */
 }
 
+#ifdef USE_LIBXSLT
 
 static void
 parse_params(const char **params, text *paramstr)
@@ -173,3 +193,5 @@ parse_params(const char **params, text *paramstr)
 
 	params[i] = NULL;
 }
+
+#endif /* USE_LIBXSLT */
-- 
GitLab