From 7559e7f746a4641011609f0f678daacef9429ca6 Mon Sep 17 00:00:00 2001
From: Laurenz Albe <laurenz.albe@wien.gv.at>
Date: Tue, 25 Oct 2016 15:16:44 +0200
Subject: [PATCH] Add PGDLLEXPORT to PG_FUNCTION_INFO_V1 function declaration

On Windows, the function and info function must be exported.  Our normal
build processes take care of that via .DEF files or --export-all-symbols.
Module authors using a different build process might do it differently,
so we declare these functions PGDLLEXPORT for their convenience.

MSVC builds fail if there are several declarations of the same function,
some of which have PGDLLEXPORT and some don't, so we have to decorate
the declarations in the ltree and hstore contrib modules accordingly.

Also, remove xml2's xml_is_well_formed() since it would clash with the
function of the same name declared in utils/xml.h.  This has been there
only to support users who didn't upgrade their C function definitions
since the function has been moved into core in 9.1 (commit a0b7b717a4).

Since commit e7128e8d the best practice is not to add a declaration to
an SQL function in an external module; modify the documentation to
reflect that.
---
 contrib/hstore/hstore.h |    4 ++--
 contrib/ltree/ltree.h   |   40 ++++++++++++++++++++--------------------
 contrib/xml2/xpath.c    |   45 ---------------------------------------------
 doc/src/sgml/xfunc.sgml |    6 +++---
 src/include/fmgr.h      |    7 +++----
 5 files changed, 28 insertions(+), 74 deletions(-)

diff --git a/contrib/hstore/hstore.h b/contrib/hstore/hstore.h
index 6bab08b..99f9eee 100644
--- a/contrib/hstore/hstore.h
+++ b/contrib/hstore/hstore.h
@@ -194,8 +194,8 @@ extern Pairs *hstoreArrayToPairs(ArrayType *a, int *npairs);
 #if HSTORE_POLLUTE_NAMESPACE
 #define HSTORE_POLLUTE(newname_,oldname_) \
 	PG_FUNCTION_INFO_V1(oldname_);		  \
-	Datum newname_(PG_FUNCTION_ARGS);	  \
-	Datum oldname_(PG_FUNCTION_ARGS) { return newname_(fcinfo); } \
+	PGDLLEXPORT Datum newname_(PG_FUNCTION_ARGS);	  \
+	PGDLLEXPORT Datum oldname_(PG_FUNCTION_ARGS) { return newname_(fcinfo); } \
 	extern int no_such_variable
 #else
 #define HSTORE_POLLUTE(newname_,oldname_) \
diff --git a/contrib/ltree/ltree.h b/contrib/ltree/ltree.h
index c604357..28bc2d7 100644
--- a/contrib/ltree/ltree.h
+++ b/contrib/ltree/ltree.h
@@ -130,30 +130,30 @@ typedef struct
 
 
 /* use in array iterator */
-Datum		ltree_isparent(PG_FUNCTION_ARGS);
-Datum		ltree_risparent(PG_FUNCTION_ARGS);
-Datum		ltq_regex(PG_FUNCTION_ARGS);
-Datum		ltq_rregex(PG_FUNCTION_ARGS);
-Datum		lt_q_regex(PG_FUNCTION_ARGS);
-Datum		lt_q_rregex(PG_FUNCTION_ARGS);
-Datum		ltxtq_exec(PG_FUNCTION_ARGS);
-Datum		ltxtq_rexec(PG_FUNCTION_ARGS);
-Datum		_ltq_regex(PG_FUNCTION_ARGS);
-Datum		_ltq_rregex(PG_FUNCTION_ARGS);
-Datum		_lt_q_regex(PG_FUNCTION_ARGS);
-Datum		_lt_q_rregex(PG_FUNCTION_ARGS);
-Datum		_ltxtq_exec(PG_FUNCTION_ARGS);
-Datum		_ltxtq_rexec(PG_FUNCTION_ARGS);
-Datum		_ltree_isparent(PG_FUNCTION_ARGS);
-Datum		_ltree_risparent(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum		ltree_isparent(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum		ltree_risparent(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum		ltq_regex(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum		ltq_rregex(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum		lt_q_regex(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum		lt_q_rregex(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum		ltxtq_exec(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum		ltxtq_rexec(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum		_ltq_regex(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum		_ltq_rregex(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum		_lt_q_regex(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum		_lt_q_rregex(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum		_ltxtq_exec(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum		_ltxtq_rexec(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum		_ltree_isparent(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum		_ltree_risparent(PG_FUNCTION_ARGS);
 
 /* Concatenation functions */
-Datum		ltree_addltree(PG_FUNCTION_ARGS);
-Datum		ltree_addtext(PG_FUNCTION_ARGS);
-Datum		ltree_textadd(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum		ltree_addltree(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum		ltree_addtext(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum		ltree_textadd(PG_FUNCTION_ARGS);
 
 /* Util function */
-Datum		ltree_in(PG_FUNCTION_ARGS);
+PGDLLEXPORT Datum		ltree_in(PG_FUNCTION_ARGS);
 
 bool ltree_execute(ITEM *curitem, void *checkval,
 			  bool calcnot, bool (*chkcond) (void *checkval, ITEM *val));
diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index ac28996..28445be 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -81,51 +81,6 @@ pgxml_parser_init(PgXmlStrictness strictness)
 }
 
 
-/*
- * 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);
-
-Datum
-xml_is_well_formed(PG_FUNCTION_ARGS)
-{
-	text	   *t = PG_GETARG_TEXT_P(0);		/* document buffer */
-	bool		result = false;
-	int32		docsize = VARSIZE(t) - VARHDRSZ;
-	xmlDocPtr	doctree;
-	PgXmlErrorContext *xmlerrcxt;
-
-	xmlerrcxt = pgxml_parser_init(PG_XML_STRICTNESS_LEGACY);
-
-	PG_TRY();
-	{
-		doctree = xmlParseMemory((char *) VARDATA(t), docsize);
-
-		result = (doctree != NULL);
-
-		if (doctree != NULL)
-			xmlFreeDoc(doctree);
-	}
-	PG_CATCH();
-	{
-		pg_xml_done(xmlerrcxt, true);
-
-		PG_RE_THROW();
-	}
-	PG_END_TRY();
-
-	pg_xml_done(xmlerrcxt, false);
-
-	PG_RETURN_BOOL(result);
-}
-
-
 /* Encodes special characters (<, >, &, " and \r) as XML entities */
 
 PG_FUNCTION_INFO_V1(xml_encode_special_chars);
diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml
index de6a466..9004063 100644
--- a/doc/src/sgml/xfunc.sgml
+++ b/doc/src/sgml/xfunc.sgml
@@ -2280,13 +2280,13 @@ CREATE FUNCTION concat_text(text, text) RETURNS text
      of the complexity of passing arguments and results.  The C declaration
      of a version-1 function is always:
 <programlisting>
-Datum funcname(PG_FUNCTION_ARGS)
+PGDLLEXPORT Datum funcname(PG_FUNCTION_ARGS)
 </programlisting>
-     In addition, the macro call:
+     This is declared automatically by the macro call:
 <programlisting>
 PG_FUNCTION_INFO_V1(funcname);
 </programlisting>
-     must appear in the same source file.  (Conventionally, it's
+     which must appear in the same source file.  (Conventionally, it's
      written just before the function itself.)  This macro call is not
      needed for <literal>internal</>-language functions, since
      <productname>PostgreSQL</> assumes that all internal functions
diff --git a/src/include/fmgr.h b/src/include/fmgr.h
index 0878418..3668ac3 100644
--- a/src/include/fmgr.h
+++ b/src/include/fmgr.h
@@ -350,12 +350,11 @@ typedef const Pg_finfo_record *(*PGFInfoFunction) (void);
  *
  *	On Windows, the function and info function must be exported.  Our normal
  *	build processes take care of that via .DEF files or --export-all-symbols.
- *	Module authors using a different build process might need to manually
- *	declare the function PGDLLEXPORT.  We do that automatically here for the
- *	info function, since authors shouldn't need to be explicitly aware of it.
+ *	Module authors using a different build process might do it differently,
+ *	so we declare these functions PGDLLEXPORT for their convenience.
  */
 #define PG_FUNCTION_INFO_V1(funcname) \
-extern Datum funcname(PG_FUNCTION_ARGS); \
+extern PGDLLEXPORT Datum funcname(PG_FUNCTION_ARGS); \
 extern PGDLLEXPORT const Pg_finfo_record * CppConcat(pg_finfo_,funcname)(void); \
 const Pg_finfo_record * \
 CppConcat(pg_finfo_,funcname) (void) \
-- 
1.7.1

