diff options
author | Michael P | 2011-07-05 03:16:11 +0000 |
---|---|---|
committer | Michael P | 2011-07-06 03:40:35 +0000 |
commit | 0bbfc1e6338b5d98d6cb83fa75f2c38f527d4d4b (patch) | |
tree | 46fa412a31d08ea6e53d488ae7bc231df0b273da /contrib/xml2/xpath.c | |
parent | 091b0e828cf0fd5bbd1f9ae58ab96fc983e55d77 (diff) | |
parent | a4bebdd92624e018108c2610fc3f2c1584b6c687 (diff) |
Merge commit 'a4bebdd92624e018108c2610fc3f2c1584b6c687' into master
This is the commit merge of Postgres-XC with the intersection of
PostgreSQL REL9_1_STABLE and master branches.
Conflicts:
COPYRIGHT
contrib/pgbench/pgbench.c
src/Makefile
src/backend/access/transam/recovery.conf.sample
src/backend/access/transam/varsup.c
src/backend/access/transam/xlog.c
src/backend/catalog/Makefile
src/backend/catalog/dependency.c
src/backend/catalog/system_views.sql
src/backend/commands/copy.c
src/backend/commands/explain.c
src/backend/commands/sequence.c
src/backend/commands/tablecmds.c
src/backend/commands/vacuum.c
src/backend/executor/nodeAgg.c
src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/nodes/outfuncs.c
src/backend/nodes/readfuncs.c
src/backend/optimizer/path/allpaths.c
src/backend/optimizer/plan/createplan.c
src/backend/optimizer/plan/setrefs.c
src/backend/parser/gram.y
src/backend/parser/parse_utilcmd.c
src/backend/postmaster/postmaster.c
src/backend/rewrite/rewriteHandler.c
src/backend/storage/lmgr/proc.c
src/backend/tcop/postgres.c
src/backend/utils/adt/ruleutils.c
src/backend/utils/init/postinit.c
src/backend/utils/misc/guc.c
src/backend/utils/misc/postgresql.conf.sample
src/backend/utils/sort/tuplesort.c
src/bin/initdb/initdb.c
src/bin/pg_ctl/pg_ctl.c
src/bin/pg_dump/pg_dump.c
src/include/access/xlog.h
src/include/catalog/catversion.h
src/include/catalog/indexing.h
src/include/catalog/pg_aggregate.h
src/include/catalog/pg_proc.h
src/include/commands/copy.h
src/include/nodes/parsenodes.h
src/include/nodes/primnodes.h
src/include/optimizer/pathnode.h
src/include/parser/kwlist.h
src/include/storage/procarray.h
src/test/regress/expected/.gitignore
src/test/regress/expected/aggregates.out
src/test/regress/expected/alter_table.out
src/test/regress/expected/bit.out
src/test/regress/expected/box.out
src/test/regress/expected/delete.out
src/test/regress/expected/float4.out
src/test/regress/expected/float8.out
src/test/regress/expected/int2.out
src/test/regress/expected/int8.out
src/test/regress/expected/interval.out
src/test/regress/expected/numeric.out
src/test/regress/expected/point.out
src/test/regress/expected/polygon.out
src/test/regress/expected/sequence.out
src/test/regress/expected/timestamp.out
src/test/regress/expected/timestamptz.out
src/test/regress/expected/transactions.out
src/test/regress/expected/window.out
src/test/regress/input/misc.source
src/test/regress/output/create_misc_1.source
src/test/regress/output/misc.source
src/test/regress/sql/aggregates.sql
src/test/regress/sql/alter_table.sql
src/test/regress/sql/bit.sql
src/test/regress/sql/box.sql
src/test/regress/sql/delete.sql
src/test/regress/sql/domain.sql
src/test/regress/sql/float4.sql
src/test/regress/sql/float8.sql
src/test/regress/sql/int2.sql
src/test/regress/sql/int8.sql
src/test/regress/sql/interval.sql
src/test/regress/sql/lseg.sql
src/test/regress/sql/numeric.sql
src/test/regress/sql/path.sql
src/test/regress/sql/point.sql
src/test/regress/sql/polygon.sql
src/test/regress/sql/portals.sql
src/test/regress/sql/sequence.sql
src/test/regress/sql/timestamp.sql
src/test/regress/sql/timestamptz.sql
src/test/regress/sql/transactions.sql
src/test/regress/sql/window.sql
src/test/regress/sql/with.sql
Diffstat (limited to 'contrib/xml2/xpath.c')
-rw-r--r-- | contrib/xml2/xpath.c | 173 |
1 files changed, 99 insertions, 74 deletions
diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c index dbf0b76f92..44c600e134 100644 --- a/contrib/xml2/xpath.c +++ b/contrib/xml2/xpath.c @@ -1,5 +1,5 @@ /* - * $PostgreSQL: pgsql/contrib/xml2/xpath.c,v 1.30 2010/07/06 19:18:55 momjian Exp $ + * contrib/xml2/xpath.c * * Parser interface for DOM-based parser (libxml) rather than * stream-based SAX-type parser @@ -40,6 +40,15 @@ Datum xpath_table(PG_FUNCTION_ARGS); void pgxml_parser_init(void); +/* workspace for pgxml_xpath() */ + +typedef struct +{ + xmlDocPtr doctree; + xmlXPathContextPtr ctxt; + xmlXPathObjectPtr res; +} xpath_workspace; + /* local declarations */ static xmlChar *pgxmlNodeSetToText(xmlNodeSetPtr nodeset, @@ -51,7 +60,10 @@ static text *pgxml_result_to_text(xmlXPathObjectPtr res, xmlChar *toptag, static xmlChar *pgxml_texttoxmlchar(text *textstring); -static xmlXPathObjectPtr pgxml_xpath(text *document, xmlChar *xpath); +static xmlXPathObjectPtr pgxml_xpath(text *document, xmlChar *xpath, + xpath_workspace *workspace); + +static void cleanup_workspace(xpath_workspace *workspace); /* @@ -71,7 +83,14 @@ pgxml_parser_init(void) } -/* Returns true if document is well-formed */ +/* + * Returns true if document is well-formed + * + * Note: this has been superseded by a core function. We still have to + * have it in the contrib module so that existing SQL-level references + * to the function won't fail; but in normal usage with up-to-date SQL + * definitions for the contrib module, this won't be called. + */ PG_FUNCTION_INFO_V1(xml_is_well_formed); @@ -214,25 +233,22 @@ PG_FUNCTION_INFO_V1(xpath_nodeset); Datum xpath_nodeset(PG_FUNCTION_ARGS) { - xmlChar *xpath, - *toptag, - *septag; - int32 pathsize; - text *xpathsupp, - *xpres; - - /* PG_GETARG_TEXT_P(0) is document buffer */ - xpathsupp = PG_GETARG_TEXT_P(1); /* XPath expression */ + text *document = PG_GETARG_TEXT_P(0); + text *xpathsupp = PG_GETARG_TEXT_P(1); /* XPath expression */ + xmlChar *toptag = pgxml_texttoxmlchar(PG_GETARG_TEXT_P(2)); + xmlChar *septag = pgxml_texttoxmlchar(PG_GETARG_TEXT_P(3)); + xmlChar *xpath; + text *xpres; + xmlXPathObjectPtr res; + xpath_workspace workspace; - toptag = pgxml_texttoxmlchar(PG_GETARG_TEXT_P(2)); - septag = pgxml_texttoxmlchar(PG_GETARG_TEXT_P(3)); + xpath = pgxml_texttoxmlchar(xpathsupp); - pathsize = VARSIZE(xpathsupp) - VARHDRSZ; + res = pgxml_xpath(document, xpath, &workspace); - xpath = pgxml_texttoxmlchar(xpathsupp); + xpres = pgxml_result_to_text(res, toptag, septag, NULL); - xpres = pgxml_result_to_text(pgxml_xpath(PG_GETARG_TEXT_P(0), xpath), - toptag, septag, NULL); + cleanup_workspace(&workspace); pfree(xpath); @@ -250,23 +266,21 @@ PG_FUNCTION_INFO_V1(xpath_list); Datum xpath_list(PG_FUNCTION_ARGS) { - xmlChar *xpath, - *plainsep; - int32 pathsize; - text *xpathsupp, - *xpres; - - /* PG_GETARG_TEXT_P(0) is document buffer */ - xpathsupp = PG_GETARG_TEXT_P(1); /* XPath expression */ + text *document = PG_GETARG_TEXT_P(0); + text *xpathsupp = PG_GETARG_TEXT_P(1); /* XPath expression */ + xmlChar *plainsep = pgxml_texttoxmlchar(PG_GETARG_TEXT_P(2)); + xmlChar *xpath; + text *xpres; + xmlXPathObjectPtr res; + xpath_workspace workspace; - plainsep = pgxml_texttoxmlchar(PG_GETARG_TEXT_P(2)); + xpath = pgxml_texttoxmlchar(xpathsupp); - pathsize = VARSIZE(xpathsupp) - VARHDRSZ; + res = pgxml_xpath(document, xpath, &workspace); - xpath = pgxml_texttoxmlchar(xpathsupp); + xpres = pgxml_result_to_text(res, NULL, NULL, plainsep); - xpres = pgxml_result_to_text(pgxml_xpath(PG_GETARG_TEXT_P(0), xpath), - NULL, NULL, plainsep); + cleanup_workspace(&workspace); pfree(xpath); @@ -281,13 +295,13 @@ PG_FUNCTION_INFO_V1(xpath_string); Datum xpath_string(PG_FUNCTION_ARGS) { + text *document = PG_GETARG_TEXT_P(0); + text *xpathsupp = PG_GETARG_TEXT_P(1); /* XPath expression */ xmlChar *xpath; int32 pathsize; - text *xpathsupp, - *xpres; - - /* PG_GETARG_TEXT_P(0) is document buffer */ - xpathsupp = PG_GETARG_TEXT_P(1); /* XPath expression */ + text *xpres; + xmlXPathObjectPtr res; + xpath_workspace workspace; pathsize = VARSIZE(xpathsupp) - VARHDRSZ; @@ -298,13 +312,16 @@ xpath_string(PG_FUNCTION_ARGS) /* We could try casting to string using the libxml function? */ xpath = (xmlChar *) palloc(pathsize + 9); - memcpy((char *) (xpath + 7), VARDATA(xpathsupp), pathsize); strncpy((char *) xpath, "string(", 7); + memcpy((char *) (xpath + 7), VARDATA(xpathsupp), pathsize); xpath[pathsize + 7] = ')'; xpath[pathsize + 8] = '\0'; - xpres = pgxml_result_to_text(pgxml_xpath(PG_GETARG_TEXT_P(0), xpath), - NULL, NULL, NULL); + res = pgxml_xpath(document, xpath, &workspace); + + xpres = pgxml_result_to_text(res, NULL, NULL, NULL); + + cleanup_workspace(&workspace); pfree(xpath); @@ -319,21 +336,17 @@ PG_FUNCTION_INFO_V1(xpath_number); Datum xpath_number(PG_FUNCTION_ARGS) { + text *document = PG_GETARG_TEXT_P(0); + text *xpathsupp = PG_GETARG_TEXT_P(1); /* XPath expression */ xmlChar *xpath; - int32 pathsize; - text *xpathsupp; float4 fRes; - xmlXPathObjectPtr res; - - /* PG_GETARG_TEXT_P(0) is document buffer */ - xpathsupp = PG_GETARG_TEXT_P(1); /* XPath expression */ - - pathsize = VARSIZE(xpathsupp) - VARHDRSZ; + xpath_workspace workspace; xpath = pgxml_texttoxmlchar(xpathsupp); - res = pgxml_xpath(PG_GETARG_TEXT_P(0), xpath); + res = pgxml_xpath(document, xpath, &workspace); + pfree(xpath); if (res == NULL) @@ -341,6 +354,8 @@ xpath_number(PG_FUNCTION_ARGS) fRes = xmlXPathCastToNumber(res); + cleanup_workspace(&workspace); + if (xmlXPathIsNaN(fRes)) PG_RETURN_NULL(); @@ -353,21 +368,17 @@ PG_FUNCTION_INFO_V1(xpath_bool); Datum xpath_bool(PG_FUNCTION_ARGS) { + text *document = PG_GETARG_TEXT_P(0); + text *xpathsupp = PG_GETARG_TEXT_P(1); /* XPath expression */ xmlChar *xpath; - int32 pathsize; - text *xpathsupp; int bRes; - xmlXPathObjectPtr res; - - /* PG_GETARG_TEXT_P(0) is document buffer */ - xpathsupp = PG_GETARG_TEXT_P(1); /* XPath expression */ - - pathsize = VARSIZE(xpathsupp) - VARHDRSZ; + xpath_workspace workspace; xpath = pgxml_texttoxmlchar(xpathsupp); - res = pgxml_xpath(PG_GETARG_TEXT_P(0), xpath); + res = pgxml_xpath(document, xpath, &workspace); + pfree(xpath); if (res == NULL) @@ -375,6 +386,8 @@ xpath_bool(PG_FUNCTION_ARGS) bRes = xmlXPathCastToBoolean(res); + cleanup_workspace(&workspace); + PG_RETURN_BOOL(bRes); } @@ -383,49 +396,61 @@ xpath_bool(PG_FUNCTION_ARGS) /* Core function to evaluate XPath query */ static xmlXPathObjectPtr -pgxml_xpath(text *document, xmlChar *xpath) +pgxml_xpath(text *document, xmlChar *xpath, xpath_workspace *workspace) { - xmlDocPtr doctree; - xmlXPathContextPtr ctxt; + int32 docsize = VARSIZE(document) - VARHDRSZ; xmlXPathObjectPtr res; xmlXPathCompExprPtr comppath; - int32 docsize; - docsize = VARSIZE(document) - VARHDRSZ; + workspace->doctree = NULL; + workspace->ctxt = NULL; + workspace->res = NULL; pgxml_parser_init(); - doctree = xmlParseMemory((char *) VARDATA(document), docsize); - if (doctree == NULL) + workspace->doctree = xmlParseMemory((char *) VARDATA(document), docsize); + if (workspace->doctree == NULL) return NULL; /* not well-formed */ - ctxt = xmlXPathNewContext(doctree); - ctxt->node = xmlDocGetRootElement(doctree); + workspace->ctxt = xmlXPathNewContext(workspace->doctree); + workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree); /* compile the path */ comppath = xmlXPathCompile(xpath); if (comppath == NULL) { - xmlFreeDoc(doctree); + cleanup_workspace(workspace); xml_ereport(ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION, "XPath Syntax Error"); } /* Now evaluate the path expression. */ - res = xmlXPathCompiledEval(comppath, ctxt); + res = xmlXPathCompiledEval(comppath, workspace->ctxt); + workspace->res = res; + xmlXPathFreeCompExpr(comppath); if (res == NULL) - { - xmlXPathFreeContext(ctxt); - xmlFreeDoc(doctree); + cleanup_workspace(workspace); - return NULL; - } - /* xmlFreeDoc(doctree); */ return res; } +/* Clean up after processing the result of pgxml_xpath() */ +static void +cleanup_workspace(xpath_workspace *workspace) +{ + if (workspace->res) + xmlXPathFreeObject(workspace->res); + workspace->res = NULL; + if (workspace->ctxt) + xmlXPathFreeContext(workspace->ctxt); + workspace->ctxt = NULL; + if (workspace->doctree) + xmlFreeDoc(workspace->doctree); + workspace->doctree = NULL; +} + static text * pgxml_result_to_text(xmlXPathObjectPtr res, xmlChar *toptag, |