Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/backend/parser/parse_clause.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ sortby_nulls_hook_type sortby_nulls_hook = NULL;

optimize_explicit_cast_hook_type optimize_explicit_cast_hook = NULL;

pre_transform_openxml_columns_hook_type pre_transform_openxml_columns_hook = NULL;

static int extractRemainingColumns(ParseState *pstate,
ParseNamespaceColumn *src_nscolumns,
List *src_colnames,
Expand Down Expand Up @@ -711,6 +713,13 @@ transformRangeTableFunc(ParseState *pstate, RangeTableFunc *rtf)
constructName = "XMLTABLE";
docType = XMLOID;

/*
* Hook to allow extensions to pre-process OPENXML column definitions
* before standard XMLTABLE transformation.
*/
if (pre_transform_openxml_columns_hook && tf->functype == TFT_XMLTABLE)
pre_transform_openxml_columns_hook(pstate, rtf);

/*
* We make lateral_only names of this level visible, whether or not the
* RangeTableFunc is explicitly marked LATERAL. This is needed for SQL
Expand Down
27 changes: 27 additions & 0 deletions src/backend/utils/adt/xml.c
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,10 @@ const TableFuncRoutine XmlTableRoutine =
.DestroyOpaque = XmlTableDestroyOpaque
};

#ifdef USE_LIBXML
openxml_set_namespaces_hook_type openxml_set_namespaces_hook = NULL;
#endif

#define NO_XML_SUPPORT() \
ereport(ERROR, \
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), \
Expand Down Expand Up @@ -4795,6 +4799,10 @@ XmlTableSetNamespace(TableFuncScanState *state, const char *name, const char *ur
errmsg("DEFAULT namespace is not supported")));
xtCxt = GetXmlTableBuilderPrivateData(state, "XmlTableSetNamespace");

/* For TSQL OPENXML, following hook will fetch and register namespaces in Xpath context. */
if (openxml_set_namespaces_hook)
return openxml_set_namespaces_hook(xtCxt->xpathcxt, xtCxt->xmlerrcxt, uri);

if (xmlXPathRegisterNs(xtCxt->xpathcxt,
pg_xmlCharStrndup(name, strlen(name)),
pg_xmlCharStrndup(uri, strlen(uri))))
Expand Down Expand Up @@ -5114,3 +5122,22 @@ XmlTableDestroyOpaque(TableFuncScanState *state)
NO_XML_SUPPORT();
#endif /* not USE_LIBXML */
}

#ifdef USE_LIBXML
xmlDocPtr
xml_parse_wrapper(text *data, XmlOptionType xmloption_arg,
bool preserve_whitespace, int encoding,
XmlOptionType *parsed_xmloptiontype, xmlNodePtr *parsed_nodes,
Node *escontext)
{
return xml_parse(data, xmloption_arg, preserve_whitespace,
encoding, parsed_xmloptiontype, parsed_nodes, escontext);
}

xmlChar *
pg_xmlCharStrndup_wrapper(const char *str, size_t len)
{
return pg_xmlCharStrndup(str, len);
}

#endif /* USE_LIBXML */
4 changes: 4 additions & 0 deletions src/include/parser/parse_clause.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,8 @@ extern PGDLLEXPORT optimize_explicit_cast_hook_type optimize_explicit_cast_hook;
/* functions in parse_jsontable.c */
extern ParseNamespaceItem *transformJsonTable(ParseState *pstate, JsonTable *jt);

/* Hook for preprocessing OPENXML column definitions before XMLTABLE transformation */
typedef void (*pre_transform_openxml_columns_hook_type) (ParseState *pstate, RangeTableFunc *rtf);
extern PGDLLIMPORT pre_transform_openxml_columns_hook_type pre_transform_openxml_columns_hook;

#endif /* PARSE_CLAUSE_H */
15 changes: 15 additions & 0 deletions src/include/utils/xml.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
#include "fmgr.h"
#include "nodes/execnodes.h"
#include "nodes/primnodes.h"
#ifdef USE_LIBXML
#include <libxml/tree.h>
#include <libxml/xpath.h>
#endif

typedef struct varlena xmltype;

Expand Down Expand Up @@ -85,6 +89,17 @@ extern char *map_sql_identifier_to_xml_name(const char *ident, bool fully_escape
extern char *map_xml_name_to_sql_identifier(const char *name);
extern char *map_sql_value_to_xml_value(Datum value, Oid type, bool xml_escape_strings);

#ifdef USE_LIBXML
extern xmlDocPtr xml_parse_wrapper(text *data, XmlOptionType xmloption_arg,
bool preserve_whitespace, int encoding,
XmlOptionType *parsed_xmloptiontype, xmlNodePtr *parsed_nodes,
Node *escontext);
extern xmlChar *pg_xmlCharStrndup_wrapper(const char *str, size_t len);
/* Hook function type for TSQL OPENXML namespace handling */
typedef void (*openxml_set_namespaces_hook_type) (xmlXPathContext *xpathctx, PgXmlErrorContext *xmlerrcxt, char *doc_id_str);
extern PGDLLIMPORT openxml_set_namespaces_hook_type openxml_set_namespaces_hook;
#endif /* USE_LIBXML */

extern PGDLLIMPORT int xmlbinary; /* XmlBinaryType, but int for guc enum */

extern PGDLLIMPORT int xmloption; /* XmlOptionType, but int for guc enum */
Expand Down