diff --git a/mysql-test/r/xml.result b/mysql-test/r/xml.result
index 3ed3df546d1..f9b8e9c9dab 100644
--- a/mysql-test/r/xml.result
+++ b/mysql-test/r/xml.result
@@ -65,6 +65,9 @@ c1
SELECT extractValue(@xml,'/a/child::*');
extractValue(@xml,'/a/child::*')
b1 b2
+SELECT extractValue(@xml,'/a/self::*');
+extractValue(@xml,'/a/self::*')
+a1 a2
SELECT extractValue(@xml,'/a/descendant::*');
extractValue(@xml,'/a/descendant::*')
b1 c1 b2
@@ -546,3 +549,12 @@ select extractvalue('A','/');
ERROR HY000: XPATH syntax error: '>'
select extractvalue('bb!','//b!');
ERROR HY000: XPATH syntax error: '!'
+select extractvalue('ABC','/a/descendant::*');
+extractvalue('ABC','/a/descendant::*')
+B C
+select extractvalue('ABC','/a/self::*');
+extractvalue('ABC','/a/self::*')
+A
+select extractvalue('ABC','/a/descendant-or-self::*');
+extractvalue('ABC','/a/descendant-or-self::*')
+A B C
diff --git a/mysql-test/t/xml.test b/mysql-test/t/xml.test
index e69ab5ee58b..ee4f7a94ba2 100644
--- a/mysql-test/t/xml.test
+++ b/mysql-test/t/xml.test
@@ -23,6 +23,7 @@ SELECT extractValue(@xml,'/*/*');
SELECT extractValue(@xml,'/*/*/*');
SELECT extractValue(@xml,'/a/child::*');
+SELECT extractValue(@xml,'/a/self::*');
SELECT extractValue(@xml,'/a/descendant::*');
SELECT extractValue(@xml,'/a/descendant-or-self::*');
SELECT extractValue(@xml,'/a/attribute::*');
@@ -243,3 +244,10 @@ select extractvalue('A','/');
#
--error 1105
select extractvalue('bb!','//b!');
+
+#
+# Bug #16315 XML: extractvalue() handles self badly
+#
+select extractvalue('ABC','/a/descendant::*');
+select extractvalue('ABC','/a/self::*');
+select extractvalue('ABC','/a/descendant-or-self::*');
diff --git a/sql/item_xmlfunc.cc b/sql/item_xmlfunc.cc
index aad9e12f6c5..8fc3a2b170c 100644
--- a/sql/item_xmlfunc.cc
+++ b/sql/item_xmlfunc.cc
@@ -252,6 +252,18 @@ public:
};
+/* Returns self */
+class Item_nodeset_func_selfbyname: public Item_nodeset_func_axisbyname
+{
+public:
+ Item_nodeset_func_selfbyname(Item *a, const char *n_arg, uint l_arg,
+ String *pxml):
+ Item_nodeset_func_axisbyname(a, n_arg, l_arg, pxml) {}
+ const char *func_name() const { return "xpath_selfbyname"; }
+ String *val_nodeset(String *nodeset);
+};
+
+
/* Returns children */
class Item_nodeset_func_childbyname: public Item_nodeset_func_axisbyname
{
@@ -572,6 +584,20 @@ String * Item_nodeset_func_union::val_nodeset(String *nodeset)
}
+String *Item_nodeset_func_selfbyname::val_nodeset(String *nodeset)
+{
+ prepare(nodeset);
+ for (MY_XPATH_FLT *flt= fltbeg; flt < fltend; flt++)
+ {
+ uint pos= 0;
+ MY_XML_NODE *self= &nodebeg[flt->num];
+ if (validname(self))
+ ((XPathFilter*)nodeset)->append_element(flt->num,pos++);
+ }
+ return nodeset;
+}
+
+
String *Item_nodeset_func_childbyname::val_nodeset(String *nodeset)
{
prepare(nodeset);
@@ -945,6 +971,9 @@ static Item* nametestfunc(MY_XPATH *xpath,
case MY_XPATH_AXIS_ATTRIBUTE:
res= new Item_nodeset_func_attributebyname(arg, beg, len, xpath->pxml);
break;
+ case MY_XPATH_AXIS_SELF:
+ res= new Item_nodeset_func_selfbyname(arg, beg, len, xpath->pxml);
+ break;
default:
res= new Item_nodeset_func_childbyname(arg, beg, len, xpath->pxml);
}