From 7af8e8d671c548f7ba43a5a9aba691ffa0fc1727 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 1 Mar 2010 18:08:27 +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 | 17 ++++-- contrib/xml2/expected/xml2_1.out | 102 +++++++++++++++++++++++++++++++ contrib/xml2/pgxml.sql.in | 9 --- contrib/xml2/xslt_proc.c | 23 ++++++- 4 files changed, 135 insertions(+), 16 deletions(-) create mode 100644 contrib/xml2/expected/xml2_1.out diff --git a/contrib/xml2/Makefile b/contrib/xml2/Makefile index c247fca300..fdc66bdfc1 100644 --- a/contrib/xml2/Makefile +++ b/contrib/xml2/Makefile @@ -1,20 +1,28 @@ # This makefile will build the new XML and XSLT routines. +# This module will not work without libxml2, but it will work without libxslt. +# To build without libxslt, run "gmake USE_LIBXSLT=0", or comment out the +# following line: +USE_LIBXSLT = 1 + MODULE_big = pgxml -# Remove xslt_proc.o from the following line if you don't have libxslt OBJS = xpath.o xslt_proc.o -# Remove -lxslt from the following line if you don't have libxslt. +PG_CPPFLAGS := $(shell xml2-config --cflags) + +ifeq ($(USE_LIBXSLT),1) +PG_CPPFLAGS += -DUSE_LIBXSLT SHLIB_LINK = -lxslt -lxml2 +else +SHLIB_LINK = -lxml2 +endif DATA_built = pgxml.sql DATA = uninstall_pgxml.sql REGRESS = xml2 DOCS = README.xml2 -PG_CPPFLAGS := $(shell xml2-config --cflags) - ifdef USE_PGXS PGXS := $(shell pg_config --pgxs) include $(PGXS) @@ -24,4 +32,3 @@ top_builddir = ../.. include $(top_builddir)/src/Makefile.global include $(top_srcdir)/contrib/contrib-global.mk endif - diff --git a/contrib/xml2/expected/xml2_1.out b/contrib/xml2/expected/xml2_1.out new file mode 100644 index 0000000000..ef9332ffa6 --- /dev/null +++ b/contrib/xml2/expected/xml2_1.out @@ -0,0 +1,102 @@ +-- +-- 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 xslt_process( +' + + + 1 + + + + 2 + + + + 3 + + + + 4 + + + + 5 + + +
'::text, +$$ + + + + + + + + + + + +$$::text); +ERROR: xslt_process() is not available without libxslt +CREATE TABLE xpath_test (id integer NOT NULL, t text); +INSERT INTO xpath_test VALUES (1, '1'); +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 text, date_entered date); +insert into articles (article_id, article_xml, date_entered) +values (2, '
test37
', 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('',$$ + + + + + +$$); +ERROR: xslt_process() is not available without libxslt +select xslt_process('',$$ + + + + + +$$); +ERROR: xslt_process() is not available without libxslt +create table t1 (id integer, xml_data text); +insert into t1 (id, xml_data) +values +(1, 'Some +Value'); +create index idx_xpath on t1 ( xpath_string +('/attributes/attribute[@name="attr_1"]/text()', xml_data)); diff --git a/contrib/xml2/pgxml.sql.in b/contrib/xml2/pgxml.sql.in index 4555cc8331..ecff53aea4 100644 --- a/contrib/xml2/pgxml.sql.in +++ b/contrib/xml2/pgxml.sql.in @@ -28,19 +28,14 @@ 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)' LANGUAGE SQL STRICT IMMUTABLE; @@ -51,14 +46,10 @@ CREATE OR REPLACE FUNCTION xpath_table(text,text,text,text,text) RETURNS setof r 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 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' LANGUAGE C STRICT IMMUTABLE; diff --git a/contrib/xml2/xslt_proc.c b/contrib/xml2/xslt_proc.c index 4c45422b49..f955d4fe6a 100644 --- a/contrib/xml2/xslt_proc.c +++ b/contrib/xml2/xslt_proc.c @@ -7,6 +7,8 @@ #include "funcapi.h" #include "miscadmin.h" +#ifdef USE_LIBXSLT + /* libxml includes */ #include @@ -20,11 +22,15 @@ #include #include +#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); @@ -36,13 +42,15 @@ static void parse_params(const char **params, text *paramstr); #define GET_STR(textp) DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(textp))) +#endif /* USE_LIBXSLT */ + PG_FUNCTION_INFO_V1(xslt_process); Datum xslt_process(PG_FUNCTION_ARGS) { - +#ifdef USE_LIBXSLT const char *params[MAXPARAMS + 1]; /* +1 for the terminator */ xsltStylesheetPtr stylesheet = NULL; @@ -58,7 +66,6 @@ xslt_process(PG_FUNCTION_ARGS) text *paramstr; text *tres; - if (fcinfo->nargs == 3) { paramstr = PG_GETARG_TEXT_P(2); @@ -128,8 +135,18 @@ xslt_process(PG_FUNCTION_ARGS) VARATT_SIZEP(tres) = reslen + VARHDRSZ; PG_RETURN_TEXT_P(tres); + +#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) @@ -178,3 +195,5 @@ parse_params(const char **params, text *paramstr) params[i] = NULL; } + +#endif /* USE_LIBXSLT */