summaryrefslogtreecommitdiff
path: root/sql/item_xmlfunc.cc
diff options
context:
space:
mode:
authorbar@mysql.com <>2006-03-03 18:36:14 +0400
committerbar@mysql.com <>2006-03-03 18:36:14 +0400
commitf516d1f9f21ed4ed7d3db8318553cfba22250316 (patch)
tree2b26ee2e04c02d466877f00f7d596e6d5541d0ca /sql/item_xmlfunc.cc
parentc7837821e1b3ba997ae6996c7a127cdeece3c5fc (diff)
downloadmariadb-git-f516d1f9f21ed4ed7d3db8318553cfba22250316.tar.gz
Bug#16318: XML: extractvalue() incorrectly returns last() = 1
xml.result, xml.test: Adding test case. item_xmlfunc.cc: - adding "size" member into MY_XPATH_FLT struct, to pass parent's context size when iterating in a predicate. Previously, temporaty context size was calculated instead, which is always 1. As a result, things like last() and count() didn't work fine. - adding iteration into Item_func_xpath_elementbyindex: similar to Item_func_xpath_predicate. This is to make things like last() and count() work inside square brackets.
Diffstat (limited to 'sql/item_xmlfunc.cc')
-rw-r--r--sql/item_xmlfunc.cc41
1 files changed, 29 insertions, 12 deletions
diff --git a/sql/item_xmlfunc.cc b/sql/item_xmlfunc.cc
index 26c2e84f8dd..453865e17a8 100644
--- a/sql/item_xmlfunc.cc
+++ b/sql/item_xmlfunc.cc
@@ -30,7 +30,6 @@
2. add nodeset_to_nodeset_comparator
3. add lacking functions:
- name()
- - last()
- lang()
- string()
- id()
@@ -75,6 +74,7 @@ typedef struct my_xpath_flt_st
{
uint num; /* absolute position in MY_XML_NODE array */
uint pos; /* relative position in context */
+ uint size; /* context size */
} MY_XPATH_FLT;
@@ -123,6 +123,15 @@ public:
MY_XPATH_FLT add;
add.num= num;
add.pos= pos;
+ add.size= 0;
+ return append_element(&add);
+ }
+ inline bool append_element(uint32 num, uint32 pos, uint32 size)
+ {
+ MY_XPATH_FLT add;
+ add.num= num;
+ add.pos= pos;
+ add.size= size;
return append_element(&add);
}
inline MY_XPATH_FLT *element(uint i)
@@ -451,7 +460,11 @@ public:
void fix_length_and_dec() { max_length=10; }
longlong val_int()
{
+ uint predicate_supplied_context_size;
String *res= args[0]->val_nodeset(&tmp_value);
+ if (res->length() == sizeof(MY_XPATH_FLT) &&
+ (predicate_supplied_context_size= ((MY_XPATH_FLT*)res->ptr())->size))
+ return predicate_supplied_context_size;
return res->length() / sizeof(MY_XPATH_FLT);
}
};
@@ -731,13 +744,15 @@ String *Item_nodeset_func_predicate::val_nodeset(String *str)
{
Item_nodeset_func *nodeset_func= (Item_nodeset_func*) args[0];
Item_func *comp_func= (Item_func*)args[1];
- uint pos= 0;
+ uint pos= 0, size;
prepare(str);
+ size= fltend - fltbeg;
for (MY_XPATH_FLT *flt= fltbeg; flt < fltend; flt++)
{
nodeset_func->context_cache.length(0);
((XPathFilter*)(&nodeset_func->context_cache))->append_element(flt->num,
- flt->pos);
+ flt->pos,
+ size);
if (comp_func->val_int())
((XPathFilter*)str)->append_element(flt->num, pos++);
}
@@ -747,17 +762,19 @@ String *Item_nodeset_func_predicate::val_nodeset(String *str)
String *Item_nodeset_func_elementbyindex::val_nodeset(String *nodeset)
{
+ Item_nodeset_func *nodeset_func= (Item_nodeset_func*) args[0];
prepare(nodeset);
- int index= args[1]->val_int() - 1;
- if (index >= 0)
+ MY_XPATH_FLT *flt;
+ uint pos, size= fltend - fltbeg;
+ for (pos= 0, flt= fltbeg; flt < fltend; flt++)
{
- MY_XPATH_FLT *flt;
- uint pos;
- for (pos= 0, flt= fltbeg; flt < fltend; flt++)
- {
- if (flt->pos == (uint) index || args[1]->is_bool_func())
- ((XPathFilter*)nodeset)->append_element(flt->num, pos++);
- }
+ nodeset_func->context_cache.length(0);
+ ((XPathFilter*)(&nodeset_func->context_cache))->append_element(flt->num,
+ flt->pos,
+ size);
+ int index= args[1]->val_int() - 1;
+ if (index >= 0 && (flt->pos == (uint) index || args[1]->is_bool_func()))
+ ((XPathFilter*)nodeset)->append_element(flt->num, pos++);
}
return nodeset;
}