From 9b3c3ee5d2de2987a8b0148853662018930a971f Mon Sep 17 00:00:00 2001
From: Jim Jones <jim.jones@uni-muenster.de>
Date: Sat, 7 Nov 2026 20:48:40 +0100
Subject: [PATCH v1] Treat domains over xml like xml in XMLTABLE columns

XmlTableGetValue() decided whether a column should get XML treatment
by testing typid == XMLOID, which does not look through domains.  A
column declared as a domain over xml was therefore handled like a
non-xml column: a node-set result was reduced to its string value.

Flatten domains to their base type before testing the column type.
XMLTABLE already looks through domains for boolean results, which it
maps by type category, and other places such as
map_sql_value_to_xml_value() treat domains like their base types as
well.
---
 src/backend/utils/adt/xml.c       |  3 +++
 src/test/regress/expected/xml.out | 11 +++++++++++
 src/test/regress/sql/xml.sql      |  7 +++++++
 3 files changed, 21 insertions(+)

diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c
index 44a3a21d135..6e232b02ad4 100644
--- a/src/backend/utils/adt/xml.c
+++ b/src/backend/utils/adt/xml.c
@@ -5024,6 +5024,9 @@ XmlTableGetValue(TableFuncScanState *state, int colnum,
 
 	xtCxt = GetXmlTableBuilderPrivateData(state, "XmlTableGetValue");
 
+	/* Look through domains, so that they are treated like their base type */
+	typid = getBaseType(typid);
+
 	Assert(xtCxt->xpathobj &&
 		   xtCxt->xpathobj->type == XPATH_NODESET &&
 		   xtCxt->xpathobj->nodesetval != NULL);
diff --git a/src/test/regress/expected/xml.out b/src/test/regress/expected/xml.out
index 6998745ee03..abe8a9f11f0 100644
--- a/src/test/regress/expected/xml.out
+++ b/src/test/regress/expected/xml.out
@@ -1897,6 +1897,17 @@ SELECT * FROM XMLTABLE('.' PASSING XMLELEMENT(NAME a) columns a varchar(20) PATH
  <foo/> | &lt;foo/&gt;
 (1 row)
 
+-- a column of a domain over xml behaves like an xml column
+CREATE DOMAIN xmldomain AS xml;
+SELECT * FROM XMLTABLE('/r' PASSING '<r><a>x</a><a>&lt;y&gt;</a></r>'
+                       COLUMNS x xml PATH 'a', dx xmldomain PATH 'a',
+                               s xml PATH 'string(a[2])', ds xmldomain PATH 'string(a[2])');
+            x             |            dx            |     s     |    ds     
+--------------------------+--------------------------+-----------+-----------
+ <a>x</a><a>&lt;y&gt;</a> | <a>x</a><a>&lt;y&gt;</a> | &lt;y&gt; | &lt;y&gt;
+(1 row)
+
+DROP DOMAIN xmldomain;
 SELECT xmltext(NULL);
  xmltext 
 ---------
diff --git a/src/test/regress/sql/xml.sql b/src/test/regress/sql/xml.sql
index 0581d21b03f..782345c3502 100644
--- a/src/test/regress/sql/xml.sql
+++ b/src/test/regress/sql/xml.sql
@@ -718,6 +718,13 @@ SELECT * FROM XMLTABLE('*' PASSING '<e>pre<!--c1--><?pi arg?><![CDATA[&ent1]]><n
 
 SELECT * FROM XMLTABLE('.' PASSING XMLELEMENT(NAME a) columns a varchar(20) PATH '"<foo/>"', b xml PATH '"<foo/>"');
 
+-- a column of a domain over xml behaves like an xml column
+CREATE DOMAIN xmldomain AS xml;
+SELECT * FROM XMLTABLE('/r' PASSING '<r><a>x</a><a>&lt;y&gt;</a></r>'
+                       COLUMNS x xml PATH 'a', dx xmldomain PATH 'a',
+                               s xml PATH 'string(a[2])', ds xmldomain PATH 'string(a[2])');
+DROP DOMAIN xmldomain;
+
 SELECT xmltext(NULL);
 SELECT xmltext('');
 SELECT xmltext('  ');
-- 
2.56.0

