22 #include "sql_class.h"
25 #include "sp_pcontext.h"
26 #include "sql_class.h"
57 enum my_xml_node_type type;
122 return str->append((
const char*)flt, (uint32)
sizeof(
MY_XPATH_FLT));
124 inline bool append_element(uint32 num, uint32 pos)
130 return append_element(&add);
132 inline bool append_element(uint32 num, uint32 pos, uint32
size)
138 return append_element(&add);
144 inline uint32 numelements()
157 String tmp_value, tmp2_value;
174 nodeend= (
MY_XML_NODE*) (pxml->ptr() + pxml->length());
175 numnodes= nodeend - nodebeg;
177 void prepare(
String *nodeset)
180 String *res= args[0]->val_nodeset(&tmp_value);
185 enum Type type()
const {
return XPATH_NODESET; }
189 String *res= val_nodeset(&tmp2_value);
193 active.alloc(numnodes);
194 memset(const_cast<char*>(active.ptr()), 0, numnodes);
199 for (j=0, node= nodebeg ; j < numnodes; j++, node++)
201 if (node->type == MY_XML_NODE_TEXT &&
202 node->parent == flt->num)
208 str->set_charset(collation.collation);
209 for (uint
i=0 ;
i < numnodes;
i++)
214 str->append(
" ", 1, &my_charset_latin1);
215 str->append(nodebeg[i].beg, nodebeg[i].end - nodebeg[i].beg);
220 enum Item_result result_type ()
const {
return STRING_RESULT; }
221 void fix_length_and_dec()
223 max_length= MAX_BLOB_WIDTH;
224 collation.collation= pxml->charset();
226 const char *func_name()
const {
return "nodeset"; }
235 const char *func_name()
const {
return "xpath_rootelement"; }
246 const char *func_name()
const {
return "xpath_union"; }
254 const char *node_name;
260 const char *func_name()
const {
return "xpath_axisbyname"; }
263 if (node_name[0] ==
'*')
265 return (node_namelen == (uint) (n->end - n->beg)) &&
266 !memcmp(node_name, n->beg, node_namelen);
278 const char *func_name()
const {
return "xpath_selfbyname"; }
290 const char *func_name()
const {
return "xpath_childbyname"; }
301 String *pxml,
bool need_self_arg):
303 need_self(need_self_arg) {}
304 const char *func_name()
const {
return "xpath_descendantbyname"; }
315 String *pxml,
bool need_self_arg):
317 need_self(need_self_arg) {}
318 const char *func_name()
const {
return "xpath_ancestorbyname"; }
330 const char *func_name()
const {
return "xpath_parentbyname"; }
342 const char *func_name()
const {
return "xpath_attributebyname"; }
357 const char *func_name()
const {
return "xpath_predicate"; }
368 const char *func_name()
const {
return "xpath_elementbyindex"; }
381 const char *func_name()
const {
return "xpath_bool"; }
382 bool is_bool_func() {
return 1; }
399 const char *func_name()
const {
return "xpath_cast_bool"; }
400 bool is_bool_func() {
return 1; }
403 if (args[0]->type() == XPATH_NODESET)
405 String *flt= args[0]->val_nodeset(&tmp_value);
408 return args[0]->val_real() ? 1 : 0;
420 const char *func_name()
const {
return "xpath_cast_number"; }
421 virtual double val_real() {
return args[0]->val_real(); }
435 {
return string_cache; }
436 void fix_length_and_dec() { max_length= MAX_BLOB_WIDTH; }
447 const char *func_name()
const {
return "xpath_position"; }
448 void fix_length_and_dec() { max_length=10; }
451 String *flt= args[0]->val_nodeset(&tmp_value);
466 const char *func_name()
const {
return "xpath_count"; }
467 void fix_length_and_dec() { max_length=10; }
470 uint predicate_supplied_context_size;
471 String *res= args[0]->val_nodeset(&tmp_value);
474 return predicate_supplied_context_size;
488 const char *func_name()
const {
return "xpath_sum"; }
492 String *res= args[0]->val_nodeset(&tmp_value);
495 uint numnodes= pxml->length() /
sizeof(
MY_XML_NODE);
501 for (uint j= flt->num + 1; j < numnodes; j++)
504 if (node->level <= self->level)
506 if ((node->parent == flt->num) &&
507 (node->type == MY_XML_NODE_TEXT))
511 double add= my_strntod(collation.collation, (
char*) node->beg,
512 node->end - node->beg, &end, &err);
530 enum Type type()
const {
return XPATH_NODESET_CMP; };
531 const char *func_name()
const {
return "xpath_nodeset_to_const_comparator"; }
532 bool is_bool_func() {
return 1; }
538 String *res= args[0]->val_nodeset(&tmp_nodeset);
542 uint numnodes= pxml->length() /
sizeof(
MY_XML_NODE);
547 for (uint j= flt->num + 1; j < numnodes; j++)
550 if (node->level <= self->level)
552 if ((node->parent == flt->num) &&
553 (node->type == MY_XML_NODE_TEXT))
555 fake->str_value.set(node->beg, node->end - node->beg,
556 collation.collation);
557 if (args[1]->val_int())
567 String *Item_nodeset_func_rootelement::val_nodeset(
String *nodeset)
575 String * Item_nodeset_func_union::val_nodeset(
String *nodeset)
577 uint num_nodes= pxml->length() /
sizeof(
MY_XML_NODE);
578 String set0, *s0= args[0]->val_nodeset(&set0);
579 String set1, *s1= args[1]->val_nodeset(&set1);
581 both_str.alloc(num_nodes);
582 char *
both= (
char*) both_str.ptr();
583 memset(both, 0, num_nodes);
588 for (flt= fltbeg; flt < fltend; flt++)
593 for (flt= fltbeg; flt < fltend; flt++)
597 for (uint
i= 0, pos= 0;
i < num_nodes;
i++)
606 String *Item_nodeset_func_selfbyname::val_nodeset(
String *nodeset)
614 ((
XPathFilter*)nodeset)->append_element(flt->num,pos++);
620 String *Item_nodeset_func_childbyname::val_nodeset(
String *nodeset)
626 for (uint pos= 0, j= flt->num + 1 ; j < numnodes; j++)
629 if (node->level <= self->level)
631 if ((node->parent == flt->num) &&
632 (node->type == MY_XML_NODE_TAG) &&
641 String *Item_nodeset_func_descendantbyname::val_nodeset(
String *nodeset)
648 if (need_self && validname(
self))
649 ((
XPathFilter*)nodeset)->append_element(flt->num,pos++);
650 for (uint j= flt->num + 1 ; j < numnodes ; j++)
653 if (node->level <= self->level)
655 if ((node->type == MY_XML_NODE_TAG) && validname(node))
663 String *Item_nodeset_func_ancestorbyname::val_nodeset(
String *nodeset)
668 active_str.alloc(numnodes);
669 active= (
char*) active_str.ptr();
670 memset(active, 0, numnodes);
680 if (need_self && validname(
self))
686 for (uint j= self->parent; nodebeg[j].parent != j; j= nodebeg[j].parent)
688 if (flt->num && validname(&nodebeg[j]))
696 for (uint j= 0; j < numnodes ; j++)
705 String *Item_nodeset_func_parentbyname::val_nodeset(
String *nodeset)
710 active_str.alloc(numnodes);
711 active= (
char*) active_str.ptr();
712 memset(active, 0, numnodes);
715 uint j= nodebeg[flt->num].parent;
716 if (flt->num && validname(&nodebeg[j]))
719 for (uint j= 0, pos= 0; j < numnodes ; j++)
728 String *Item_nodeset_func_attributebyname::val_nodeset(
String *nodeset)
734 for (uint pos=0, j= flt->num + 1 ; j < numnodes; j++)
737 if (node->level <= self->level)
739 if ((node->parent == flt->num) &&
740 (node->type == MY_XML_NODE_ATTR) &&
749 String *Item_nodeset_func_predicate::val_nodeset(
String *str)
755 size= fltend - fltbeg;
758 nodeset_func->context_cache.length(0);
759 ((
XPathFilter*)(&nodeset_func->context_cache))->append_element(flt->num,
762 if (comp_func->val_int())
763 ((
XPathFilter*)str)->append_element(flt->num, pos++);
769 String *Item_nodeset_func_elementbyindex::val_nodeset(
String *nodeset)
774 uint pos,
size= fltend - fltbeg;
775 for (pos= 0, flt= fltbeg; flt < fltend; flt++)
777 nodeset_func->context_cache.length(0);
778 ((
XPathFilter*)(&nodeset_func->context_cache))->append_element(flt->num,
781 int index= (int) (args[1]->val_int()) - 1;
782 if (index >= 0 && (flt->pos == (uint) index || args[1]->is_bool_func()))
783 ((
XPathFilter*)nodeset)->append_element(flt->num, pos++);
795 if (item->type() == Item::XPATH_NODESET)
804 #define MY_XPATH_LEX_DIGITS 'd'
805 #define MY_XPATH_LEX_IDENT 'i'
806 #define MY_XPATH_LEX_STRING 's'
807 #define MY_XPATH_LEX_SLASH '/'
808 #define MY_XPATH_LEX_LB '['
809 #define MY_XPATH_LEX_RB ']'
810 #define MY_XPATH_LEX_LP '('
811 #define MY_XPATH_LEX_RP ')'
812 #define MY_XPATH_LEX_EQ '='
813 #define MY_XPATH_LEX_LESS '<'
814 #define MY_XPATH_LEX_GREATER '>'
815 #define MY_XPATH_LEX_AT '@'
816 #define MY_XPATH_LEX_COLON ':'
817 #define MY_XPATH_LEX_ASTERISK '*'
818 #define MY_XPATH_LEX_DOT '.'
819 #define MY_XPATH_LEX_VLINE '|'
820 #define MY_XPATH_LEX_MINUS '-'
821 #define MY_XPATH_LEX_PLUS '+'
822 #define MY_XPATH_LEX_EXCL '!'
823 #define MY_XPATH_LEX_COMMA ','
824 #define MY_XPATH_LEX_DOLLAR '$'
825 #define MY_XPATH_LEX_ERROR 'A'
826 #define MY_XPATH_LEX_EOF 'B'
827 #define MY_XPATH_LEX_AND 'C'
828 #define MY_XPATH_LEX_OR 'D'
829 #define MY_XPATH_LEX_DIV 'E'
830 #define MY_XPATH_LEX_MOD 'F'
831 #define MY_XPATH_LEX_FUNC 'G'
832 #define MY_XPATH_LEX_NODETYPE 'H'
833 #define MY_XPATH_LEX_AXIS 'I'
834 #define MY_XPATH_LEX_LE 'J'
835 #define MY_XPATH_LEX_GE 'K'
841 #define MY_XPATH_AXIS_ANCESTOR 0
842 #define MY_XPATH_AXIS_ANCESTOR_OR_SELF 1
843 #define MY_XPATH_AXIS_ATTRIBUTE 2
844 #define MY_XPATH_AXIS_CHILD 3
845 #define MY_XPATH_AXIS_DESCENDANT 4
846 #define MY_XPATH_AXIS_DESCENDANT_OR_SELF 5
847 #define MY_XPATH_AXIS_FOLLOWING 6
848 #define MY_XPATH_AXIS_FOLLOWING_SIBLING 7
849 #define MY_XPATH_AXIS_NAMESPACE 8
850 #define MY_XPATH_AXIS_PARENT 9
851 #define MY_XPATH_AXIS_PRECEDING 10
852 #define MY_XPATH_AXIS_PRECEDING_SIBLING 11
853 #define MY_XPATH_AXIS_SELF 12
874 case MY_XPATH_LEX_GREATER:
return new Item_func_gt(a, b);
893 static Item *eq_func_reverse(
int oper,
Item *a,
Item *b)
901 case MY_XPATH_LEX_GREATER:
return new Item_func_lt(a, b);
922 if (a->type() != Item::XPATH_NODESET &&
923 b->type() != Item::XPATH_NODESET)
925 return eq_func(oper, a, b);
927 else if (a->type() == Item::XPATH_NODESET &&
928 b->type() == Item::XPATH_NODESET)
930 uint len= xpath->query.end - context->beg;
931 set_if_smaller(len, 32);
932 my_printf_error(ER_UNKNOWN_ERROR,
934 "comparison of two nodesets is not supported: '%.*s'",
935 MYF(0), len, context->beg);
950 fake->set_used_tables(RAND_TABLE_BIT);
953 if (a->type() == Item::XPATH_NODESET)
957 comp= eq_func(oper, (
Item*)fake, scalar);
963 comp= eq_func_reverse(oper, fake, scalar);
980 int type,
Item *arg,
const char *beg, uint len)
982 DBUG_ASSERT(arg != 0);
983 DBUG_ASSERT(arg->type() == Item::XPATH_NODESET);
984 DBUG_ASSERT(beg != 0);
985 DBUG_ASSERT(len > 0);
990 case MY_XPATH_AXIS_ANCESTOR:
993 case MY_XPATH_AXIS_ANCESTOR_OR_SELF:
996 case MY_XPATH_AXIS_PARENT:
999 case MY_XPATH_AXIS_DESCENDANT:
1002 case MY_XPATH_AXIS_DESCENDANT_OR_SELF:
1005 case MY_XPATH_AXIS_ATTRIBUTE:
1008 case MY_XPATH_AXIS_SELF:
1021 static char simpletok[128]=
1023 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1029 0,1,0,0,1,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,0,
1030 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,
1031 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0
1049 {MY_XPATH_LEX_AND ,
"and" , 3, 0 },
1050 {MY_XPATH_LEX_OR ,
"or" , 2, 0 },
1051 {MY_XPATH_LEX_DIV ,
"div" , 3, 0 },
1052 {MY_XPATH_LEX_MOD ,
"mod" , 3, 0 },
1059 {MY_XPATH_LEX_AXIS,
"ancestor" , 8,MY_XPATH_AXIS_ANCESTOR },
1060 {MY_XPATH_LEX_AXIS,
"ancestor-or-self" ,16,MY_XPATH_AXIS_ANCESTOR_OR_SELF },
1061 {MY_XPATH_LEX_AXIS,
"attribute" , 9,MY_XPATH_AXIS_ATTRIBUTE },
1062 {MY_XPATH_LEX_AXIS,
"child" , 5,MY_XPATH_AXIS_CHILD },
1063 {MY_XPATH_LEX_AXIS,
"descendant" ,10,MY_XPATH_AXIS_DESCENDANT },
1064 {MY_XPATH_LEX_AXIS,
"descendant-or-self",18,MY_XPATH_AXIS_DESCENDANT_OR_SELF},
1065 {MY_XPATH_LEX_AXIS,
"following" , 9,MY_XPATH_AXIS_FOLLOWING },
1066 {MY_XPATH_LEX_AXIS,
"following-sibling" ,17,MY_XPATH_AXIS_FOLLOWING_SIBLING },
1067 {MY_XPATH_LEX_AXIS,
"namespace" , 9,MY_XPATH_AXIS_NAMESPACE },
1068 {MY_XPATH_LEX_AXIS,
"parent" , 6,MY_XPATH_AXIS_PARENT },
1069 {MY_XPATH_LEX_AXIS,
"preceding" , 9,MY_XPATH_AXIS_PRECEDING },
1070 {MY_XPATH_LEX_AXIS,
"preceding-sibling" ,17,MY_XPATH_AXIS_PRECEDING_SIBLING },
1071 {MY_XPATH_LEX_AXIS,
"self" , 4,MY_XPATH_AXIS_SELF },
1078 {MY_XPATH_LEX_NODETYPE,
"comment" , 7, 0 },
1079 {MY_XPATH_LEX_NODETYPE,
"text" , 4, 0 },
1080 {MY_XPATH_LEX_NODETYPE,
"processing-instruction" , 22,0 },
1081 {MY_XPATH_LEX_NODETYPE,
"node" , 4, 0 },
1099 const char *beg,
const char *end)
1102 size_t length= end-beg;
1103 for (k= keyword_names; k->name; k++)
1105 if (length == k->length && !strncasecmp(beg, k->name, length))
1111 return MY_XPATH_LEX_IDENT;
1161 static Item *create_func_string_length(
MY_XPATH *xpath,
Item **args, uint nargs)
1163 Item *arg= nargs ? args[0] : xpath->context;
1176 return xpath->context ?
1181 static Item *create_func_position(
MY_XPATH *xpath,
Item **args, uint nargs)
1183 return xpath->context ?
1188 static Item *create_func_contains(
MY_XPATH *xpath,
Item **args, uint nargs)
1212 if (args[0]->
type() != Item::XPATH_NODESET)
1220 if (args[0]->
type() != Item::XPATH_NODESET)
1232 {
"sum", 3, 1 , 1 , create_func_sum},
1233 {
"not", 3, 1 , 1 , create_func_not},
1240 {
"last", 4, 0, 0, create_func_last},
1241 {
"true", 4, 0, 0, create_func_true},
1242 {
"name", 4, 0, 1, 0},
1243 {
"lang", 4, 1, 1, 0},
1250 {
"count", 5, 1, 1, create_func_count},
1251 {
"false", 5, 0, 0, create_func_false},
1252 {
"floor", 5, 1, 1, create_func_floor},
1253 {
"round", 5, 1, 1, create_func_round},
1260 {
"concat", 6, 2, 255, create_func_concat},
1261 {
"number", 6, 0, 1 , create_func_number},
1262 {
"string", 6, 0, 1 , 0},
1270 {
"id" , 2 , 1 , 1 , 0},
1271 {
"boolean" , 7 , 1 , 1 , create_func_bool},
1272 {
"ceiling" , 7 , 1 , 1 , create_func_ceiling},
1273 {
"position" , 8 , 0 , 0 , create_func_position},
1274 {
"contains" , 8 , 2 , 2 , create_func_contains},
1275 {
"substring" , 9 , 2 , 3 , create_func_substr},
1276 {
"translate" , 9 , 3 , 3 , 0},
1278 {
"local-name" , 10 , 0 , 1 , 0},
1279 {
"starts-with" , 11 , 2 , 2 , 0},
1280 {
"namespace-uri" , 13 , 0 , 1 , 0},
1281 {
"string-length" , 13 , 0 , 1 , create_func_string_length},
1282 {
"substring-after" , 15 , 2 , 2 , 0},
1283 {
"normalize-space" , 15 , 0 , 1 , 0},
1284 {
"substring-before" , 16 , 2 , 2 , 0},
1302 my_xpath_function(
const char *beg,
const char *end)
1305 uint length= end-beg;
1309 case 3: function_names= my_func_names3;
break;
1310 case 4: function_names= my_func_names4;
break;
1311 case 5: function_names= my_func_names5;
break;
1312 case 6: function_names= my_func_names6;
break;
1313 default: function_names= my_func_names;
1315 for (k= function_names; k->name; k++)
1316 if (k->create && length == k->length && !strncasecmp(beg, k->name, length))
1325 const char *str,
const char *strend)
1336 memset(xpath, 0,
sizeof(xpath[0]));
1343 return ((c) >=
'0' && (c) <=
'9');
1362 int ch, ctype, length;
1363 for ( ; beg < end && *beg ==
' ' ; beg++) ;
1369 lex->term= MY_XPATH_LEX_EOF;
1374 if ((length= xpath->cs->cset->ctype(xpath->cs, &ctype,
1376 (
const uchar*) end)) > 0 &&
1377 ((ctype & (_MY_L | _MY_U)) || *beg ==
'_'))
1381 (length= xpath->cs->cset->ctype(xpath->cs, &ctype,
1383 (
const uchar*) end)) > 0 &&
1384 ((ctype & (_MY_L | _MY_U | _MY_NMR)) ||
1385 *beg ==
'_' || *beg ==
'-' || *beg ==
'.') ;
1397 if ((xpath->func= my_xpath_function(lex->beg, beg)))
1398 lex->term= MY_XPATH_LEX_FUNC;
1400 lex->term= my_xpath_keyword(xpath, my_nodetype_names,
1405 else if (*beg ==
':' && beg + 1 < end && beg[1] ==
':')
1407 lex->term= my_xpath_keyword(xpath, my_axis_names,
1413 lex->term= my_xpath_keyword(xpath, my_keyword_names,
1421 if (ch > 0 && ch < 128 && simpletok[ch])
1432 for ( ; beg < end && my_xdigit(*beg) ; beg++) ;
1434 lex->term= MY_XPATH_LEX_DIGITS;
1438 if (ch ==
'"' || ch ==
'\'')
1440 for ( ; beg < end && *beg != ch ; beg++) ;
1444 lex->term= MY_XPATH_LEX_STRING;
1451 lex->term= MY_XPATH_LEX_ERROR;
1457 lex->term= MY_XPATH_LEX_ERROR;
1473 my_xpath_parse_term(
MY_XPATH *xpath,
int term)
1475 if (xpath->lasttok.term == term && !xpath->error)
1477 xpath->prevtok= xpath->lasttok;
1478 my_xpath_lex_scan(xpath, &xpath->lasttok,
1479 xpath->lasttok.end, xpath->query.end);
1496 static int my_xpath_parse_AxisName(
MY_XPATH *xpath)
1498 int rc= my_xpath_parse_term(xpath, MY_XPATH_LEX_AXIS);
1499 xpath->axis= xpath->extra;
1513 #define my_xpath_parse_PredicateExpr(x) my_xpath_parse_Expr((x))
1516 #define my_xpath_parse_Expr(x) my_xpath_parse_OrExpr((x))
1518 static int my_xpath_parse_LocationPath(
MY_XPATH *xpath);
1519 static int my_xpath_parse_AbsoluteLocationPath(
MY_XPATH *xpath);
1520 static int my_xpath_parse_RelativeLocationPath(
MY_XPATH *xpath);
1521 static int my_xpath_parse_AbbreviatedStep(
MY_XPATH *xpath);
1522 static int my_xpath_parse_Step(
MY_XPATH *xpath);
1523 static int my_xpath_parse_AxisSpecifier(
MY_XPATH *xpath);
1524 static int my_xpath_parse_NodeTest(
MY_XPATH *xpath);
1525 static int my_xpath_parse_AbbreviatedAxisSpecifier(
MY_XPATH *xpath);
1526 static int my_xpath_parse_NameTest(
MY_XPATH *xpath);
1527 static int my_xpath_parse_FunctionCall(
MY_XPATH *xpath);
1528 static int my_xpath_parse_Number(
MY_XPATH *xpath);
1529 static int my_xpath_parse_FilterExpr(
MY_XPATH *xpath);
1530 static int my_xpath_parse_PathExpr(
MY_XPATH *xpath);
1531 static int my_xpath_parse_OrExpr(
MY_XPATH *xpath);
1532 static int my_xpath_parse_UnaryExpr(
MY_XPATH *xpath);
1533 static int my_xpath_parse_MultiplicativeExpr(
MY_XPATH *xpath);
1534 static int my_xpath_parse_AdditiveExpr(
MY_XPATH *xpath);
1535 static int my_xpath_parse_RelationalExpr(
MY_XPATH *xpath);
1536 static int my_xpath_parse_AndExpr(
MY_XPATH *xpath);
1537 static int my_xpath_parse_EqualityExpr(
MY_XPATH *xpath);
1538 static int my_xpath_parse_VariableReference(
MY_XPATH *xpath);
1553 static int my_xpath_parse_LocationPath(
MY_XPATH *xpath)
1555 Item *context= xpath->context;
1557 if (!xpath->context)
1558 xpath->context= xpath->rootelement;
1559 int rc= my_xpath_parse_RelativeLocationPath(xpath) ||
1560 my_xpath_parse_AbsoluteLocationPath(xpath);
1562 xpath->item= xpath->context;
1563 xpath->context= context;
1586 static int my_xpath_parse_AbsoluteLocationPath(
MY_XPATH *xpath)
1588 if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_SLASH))
1591 xpath->context= xpath->rootelement;
1593 if (my_xpath_parse_term(xpath, MY_XPATH_LEX_SLASH))
1598 return my_xpath_parse_RelativeLocationPath(xpath);
1601 my_xpath_parse_RelativeLocationPath(xpath);
1603 return (xpath->error == 0);
1629 static int my_xpath_parse_RelativeLocationPath(
MY_XPATH *xpath)
1631 if (!my_xpath_parse_Step(xpath))
1633 while (my_xpath_parse_term(xpath, MY_XPATH_LEX_SLASH))
1635 if (my_xpath_parse_term(xpath, MY_XPATH_LEX_SLASH))
1639 if (!my_xpath_parse_Step(xpath))
1663 my_xpath_parse_AxisSpecifier_NodeTest_opt_Predicate_list(
MY_XPATH *xpath)
1665 if (!my_xpath_parse_AxisSpecifier(xpath))
1668 if (!my_xpath_parse_NodeTest(xpath))
1671 while (my_xpath_parse_term(xpath, MY_XPATH_LEX_LB))
1673 Item *prev_context= xpath->context;
1677 xpath->context_cache= context_cache;
1679 if(!my_xpath_parse_PredicateExpr(xpath))
1685 if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_RB))
1691 xpath->item= nodeset2bool(xpath, xpath->item);
1693 if (xpath->item->is_bool_func())
1710 static int my_xpath_parse_Step(
MY_XPATH *xpath)
1713 my_xpath_parse_AxisSpecifier_NodeTest_opt_Predicate_list(xpath) ||
1714 my_xpath_parse_AbbreviatedStep(xpath);
1729 static int my_xpath_parse_AbbreviatedAxisSpecifier(
MY_XPATH *xpath)
1731 if (my_xpath_parse_term(xpath, MY_XPATH_LEX_AT))
1732 xpath->axis= MY_XPATH_AXIS_ATTRIBUTE;
1734 xpath->axis= MY_XPATH_AXIS_CHILD;
1748 static int my_xpath_parse_AxisName_colon_colon(
MY_XPATH *xpath)
1750 return my_xpath_parse_AxisName(xpath) &&
1751 my_xpath_parse_term(xpath, MY_XPATH_LEX_COLON) &&
1752 my_xpath_parse_term(xpath, MY_XPATH_LEX_COLON);
1766 static int my_xpath_parse_AxisSpecifier(
MY_XPATH *xpath)
1768 return my_xpath_parse_AxisName_colon_colon(xpath) ||
1769 my_xpath_parse_AbbreviatedAxisSpecifier(xpath);
1782 static int my_xpath_parse_NodeTest_lp_rp(
MY_XPATH *xpath)
1784 return my_xpath_parse_term(xpath, MY_XPATH_LEX_NODETYPE) &&
1785 my_xpath_parse_term(xpath, MY_XPATH_LEX_LP) &&
1786 my_xpath_parse_term(xpath, MY_XPATH_LEX_RP);
1802 static int my_xpath_parse_NodeTest(
MY_XPATH *xpath)
1804 return my_xpath_parse_NameTest(xpath) ||
1805 my_xpath_parse_NodeTest_lp_rp(xpath);
1820 static int my_xpath_parse_AbbreviatedStep(
MY_XPATH *xpath)
1822 if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_DOT))
1824 if (my_xpath_parse_term(xpath, MY_XPATH_LEX_DOT))
1845 static int my_xpath_parse_lp_Expr_rp(
MY_XPATH *xpath)
1847 return my_xpath_parse_term(xpath, MY_XPATH_LEX_LP) &&
1848 my_xpath_parse_Expr(xpath) &&
1849 my_xpath_parse_term(xpath, MY_XPATH_LEX_RP);
1851 static int my_xpath_parse_PrimaryExpr_literal(
MY_XPATH *xpath)
1853 if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_STRING))
1855 xpath->item=
new Item_string(xpath->prevtok.beg + 1,
1856 xpath->prevtok.end - xpath->prevtok.beg - 2,
1860 static int my_xpath_parse_PrimaryExpr(
MY_XPATH *xpath)
1863 my_xpath_parse_lp_Expr_rp(xpath) ||
1864 my_xpath_parse_VariableReference(xpath) ||
1865 my_xpath_parse_PrimaryExpr_literal(xpath) ||
1866 my_xpath_parse_Number(xpath) ||
1867 my_xpath_parse_FunctionCall(xpath);
1883 static int my_xpath_parse_FunctionCall(
MY_XPATH *xpath)
1888 if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_FUNC))
1893 if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_LP))
1896 for (nargs= 0 ; nargs < func->maxargs; )
1898 if (!my_xpath_parse_Expr(xpath))
1900 if (nargs < func->minargs)
1904 args[nargs++]= xpath->item;
1905 if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_COMMA))
1907 if (nargs < func->minargs)
1915 if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_RP))
1918 return ((xpath->item= func->create(xpath, args, nargs))) ? 1 : 0;
1933 static int my_xpath_parse_UnionExpr(
MY_XPATH *xpath)
1935 if (!my_xpath_parse_PathExpr(xpath))
1938 while (my_xpath_parse_term(xpath, MY_XPATH_LEX_VLINE))
1940 Item *prev= xpath->item;
1941 if (prev->type() != Item::XPATH_NODESET)
1944 if (!my_xpath_parse_PathExpr(xpath)
1945 || xpath->item->type() != Item::XPATH_NODESET)
1970 my_xpath_parse_FilterExpr_opt_slashes_RelativeLocationPath(
MY_XPATH *xpath)
1972 Item *context= xpath->context;
1975 if (!my_xpath_parse_FilterExpr(xpath))
1978 if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_SLASH))
1981 if (xpath->item->type() != Item::XPATH_NODESET)
1983 xpath->lasttok= xpath->prevtok;
1992 xpath->context= xpath->item;
1995 if (my_xpath_parse_term(xpath, MY_XPATH_LEX_SLASH))
1997 "*", 1, xpath->pxml, 1);
1998 rc= my_xpath_parse_RelativeLocationPath(xpath);
2001 xpath->item= xpath->context;
2002 xpath->context= context;
2005 static int my_xpath_parse_PathExpr(
MY_XPATH *xpath)
2007 return my_xpath_parse_LocationPath(xpath) ||
2008 my_xpath_parse_FilterExpr_opt_slashes_RelativeLocationPath(xpath);
2029 static int my_xpath_parse_FilterExpr(
MY_XPATH *xpath)
2031 return my_xpath_parse_PrimaryExpr(xpath);
2046 static int my_xpath_parse_OrExpr(
MY_XPATH *xpath)
2048 if (!my_xpath_parse_AndExpr(xpath))
2051 while (my_xpath_parse_term(xpath, MY_XPATH_LEX_OR))
2053 Item *prev= xpath->item;
2054 if (!my_xpath_parse_AndExpr(xpath))
2059 xpath->item=
new Item_cond_or(nodeset2bool(xpath, prev),
2060 nodeset2bool(xpath, xpath->item));
2077 static int my_xpath_parse_AndExpr(
MY_XPATH *xpath)
2079 if (!my_xpath_parse_EqualityExpr(xpath))
2082 while (my_xpath_parse_term(xpath, MY_XPATH_LEX_AND))
2084 Item *prev= xpath->item;
2085 if (!my_xpath_parse_EqualityExpr(xpath))
2092 nodeset2bool(xpath,xpath->item));
2113 static int my_xpath_parse_ne(
MY_XPATH *xpath)
2116 if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_EXCL))
2118 if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_EQ))
2121 xpath->lasttok= xpath->prevtok;
2122 xpath->prevtok= prevtok;
2127 static int my_xpath_parse_EqualityOperator(
MY_XPATH *xpath)
2129 if (my_xpath_parse_ne(xpath))
2134 if (my_xpath_parse_term(xpath, MY_XPATH_LEX_EQ))
2141 static int my_xpath_parse_EqualityExpr(
MY_XPATH *xpath)
2144 if (!my_xpath_parse_RelationalExpr(xpath))
2147 operator_context= xpath->lasttok;
2148 while (my_xpath_parse_EqualityOperator(xpath))
2150 Item *prev= xpath->item;
2151 int oper= xpath->extra;
2152 if (!my_xpath_parse_RelationalExpr(xpath))
2158 if (!(xpath->item= create_comparator(xpath, oper, &operator_context,
2159 prev, xpath->item)))
2162 operator_context= xpath->lasttok;
2186 static int my_xpath_parse_RelationalOperator(
MY_XPATH *xpath)
2188 if (my_xpath_parse_term(xpath, MY_XPATH_LEX_LESS))
2190 xpath->extra= my_xpath_parse_term(xpath, MY_XPATH_LEX_EQ) ?
2191 MY_XPATH_LEX_LE : MY_XPATH_LEX_LESS;
2194 else if (my_xpath_parse_term(xpath, MY_XPATH_LEX_GREATER))
2196 xpath->extra= my_xpath_parse_term(xpath, MY_XPATH_LEX_EQ) ?
2197 MY_XPATH_LEX_GE : MY_XPATH_LEX_GREATER;
2202 static int my_xpath_parse_RelationalExpr(
MY_XPATH *xpath)
2205 if (!my_xpath_parse_AdditiveExpr(xpath))
2207 operator_context= xpath->lasttok;
2208 while (my_xpath_parse_RelationalOperator(xpath))
2210 Item *prev= xpath->item;
2211 int oper= xpath->extra;
2213 if (!my_xpath_parse_AdditiveExpr(xpath))
2219 if (!(xpath->item= create_comparator(xpath, oper, &operator_context,
2220 prev, xpath->item)))
2222 operator_context= xpath->lasttok;
2240 static int my_xpath_parse_AdditiveOperator(
MY_XPATH *xpath)
2242 return my_xpath_parse_term(xpath, MY_XPATH_LEX_PLUS) ||
2243 my_xpath_parse_term(xpath, MY_XPATH_LEX_MINUS);
2245 static int my_xpath_parse_AdditiveExpr(
MY_XPATH *xpath)
2247 if (!my_xpath_parse_MultiplicativeExpr(xpath))
2250 while (my_xpath_parse_AdditiveOperator(xpath))
2252 int oper= xpath->prevtok.term;
2253 Item *prev= xpath->item;
2254 if (!my_xpath_parse_MultiplicativeExpr(xpath))
2260 if (oper == MY_XPATH_LEX_PLUS)
2286 static int my_xpath_parse_MultiplicativeOperator(
MY_XPATH *xpath)
2289 my_xpath_parse_term(xpath, MY_XPATH_LEX_ASTERISK) ||
2290 my_xpath_parse_term(xpath, MY_XPATH_LEX_DIV) ||
2291 my_xpath_parse_term(xpath, MY_XPATH_LEX_MOD);
2293 static int my_xpath_parse_MultiplicativeExpr(
MY_XPATH *xpath)
2295 if (!my_xpath_parse_UnaryExpr(xpath))
2298 while (my_xpath_parse_MultiplicativeOperator(xpath))
2300 int oper= xpath->prevtok.term;
2301 Item *prev= xpath->item;
2302 if (!my_xpath_parse_UnaryExpr(xpath))
2309 case MY_XPATH_LEX_ASTERISK:
2312 case MY_XPATH_LEX_DIV:
2315 case MY_XPATH_LEX_MOD:
2335 static int my_xpath_parse_UnaryExpr(
MY_XPATH *xpath)
2337 if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_MINUS))
2338 return my_xpath_parse_UnionExpr(xpath);
2339 if (!my_xpath_parse_UnaryExpr(xpath))
2370 static int my_xpath_parse_Number(
MY_XPATH *xpath)
2373 if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_DIGITS))
2375 beg= xpath->prevtok.beg;
2376 if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_DOT))
2378 xpath->item=
new Item_int(xpath->prevtok.beg,
2379 xpath->prevtok.end - xpath->prevtok.beg);
2382 my_xpath_parse_term(xpath, MY_XPATH_LEX_DIGITS);
2384 xpath->item=
new Item_float(beg, xpath->prevtok.end - beg);
2408 my_xpath_parse_NCName(
MY_XPATH *xpath)
2411 my_xpath_parse_term(xpath, MY_XPATH_LEX_IDENT) ||
2412 my_xpath_parse_term(xpath, MY_XPATH_LEX_AND) ||
2413 my_xpath_parse_term(xpath, MY_XPATH_LEX_OR) ||
2414 my_xpath_parse_term(xpath, MY_XPATH_LEX_MOD) ||
2415 my_xpath_parse_term(xpath, MY_XPATH_LEX_DIV) ? 1 : 0;
2429 my_xpath_parse_QName(
MY_XPATH *xpath)
2432 if (!my_xpath_parse_NCName(xpath))
2434 beg= xpath->prevtok.beg;
2435 if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_COLON))
2437 if (!my_xpath_parse_NCName(xpath))
2439 xpath->prevtok.beg= beg;
2472 my_xpath_parse_VariableReference(
MY_XPATH *xpath)
2476 const char *dollar_pos;
2477 if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_DOLLAR) ||
2478 (!(dollar_pos= xpath->prevtok.beg)) ||
2479 (!((user_var= my_xpath_parse_term(xpath, MY_XPATH_LEX_AT) &&
2480 my_xpath_parse_term(xpath, MY_XPATH_LEX_IDENT))) &&
2481 !my_xpath_parse_term(xpath, MY_XPATH_LEX_IDENT)))
2484 name.length= xpath->prevtok.end - xpath->prevtok.beg;
2485 name.str= (
char*) xpath->prevtok.beg;
2494 if ((lex= current_thd->lex) &&
2495 (spc= lex->get_sp_current_parsing_ctx()) &&
2502 splocal->m_sp= lex->sphead;
2504 xpath->item= (
Item*) splocal;
2509 DBUG_ASSERT(xpath->query.end > dollar_pos);
2510 uint len= xpath->query.end - dollar_pos;
2511 set_if_smaller(len, 32);
2512 my_printf_error(ER_UNKNOWN_ERROR,
"Unknown XPATH variable at: '%.*s'",
2513 MYF(0), len, dollar_pos);
2516 return xpath->item ? 1 : 0;
2533 my_xpath_parse_NodeTest_QName(
MY_XPATH *xpath)
2535 if (!my_xpath_parse_QName(xpath))
2537 DBUG_ASSERT(xpath->context);
2538 uint len= xpath->prevtok.end - xpath->prevtok.beg;
2539 xpath->context= nametestfunc(xpath, xpath->axis, xpath->context,
2540 xpath->prevtok.beg, len);
2544 my_xpath_parse_NodeTest_asterisk(
MY_XPATH *xpath)
2546 if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_ASTERISK))
2548 DBUG_ASSERT(xpath->context);
2549 xpath->context= nametestfunc(xpath, xpath->axis, xpath->context,
"*", 1);
2553 my_xpath_parse_NameTest(
MY_XPATH *xpath)
2555 return my_xpath_parse_NodeTest_asterisk(xpath) ||
2556 my_xpath_parse_NodeTest_QName(xpath);
2572 my_xpath_parse(
MY_XPATH *xpath,
const char *str,
const char *strend)
2574 my_xpath_lex_init(&xpath->query, str, strend);
2575 my_xpath_lex_init(&xpath->prevtok, str, strend);
2576 my_xpath_lex_scan(xpath, &xpath->lasttok, str, strend);
2581 my_xpath_parse_Expr(xpath) &&
2582 my_xpath_parse_term(xpath, MY_XPATH_LEX_EOF);
2586 void Item_xml_str_func::fix_length_and_dec()
2590 if (agg_arg_charsets_for_comparison(collation, args, arg_count))
2593 if (collation.collation->mbminlen > 1)
2596 my_printf_error(ER_UNKNOWN_ERROR,
2597 "Character set '%s' is not supported by XPATH",
2598 MYF(0), collation.collation->csname);
2602 if (!args[1]->const_during_execution())
2604 my_printf_error(ER_UNKNOWN_ERROR,
2605 "Only constant XPATH queries are supported", MYF(0));
2609 if (args[1]->const_item())
2612 max_length= MAX_BLOB_WIDTH;
2620 if (!(xp= xpath_expr->val_str(&tmp)))
2623 my_xpath_init(&xpath);
2624 xpath.cs= collation.collation;
2627 pxml.set_charset(collation.collation);
2629 int rc= my_xpath_parse(&xpath, xp->ptr(), xp->ptr() + xp->length());
2633 uint clen= xpath.query.end - xpath.lasttok.beg;
2634 set_if_smaller(clen, 32);
2635 my_printf_error(ER_UNKNOWN_ERROR,
"XPATH syntax error: '%.*s'",
2636 MYF(0), clen, xpath.lasttok.beg);
2640 nodeset_func= xpath.item;
2642 nodeset_func->fix_fields(current_thd, &nodeset_func);
2646 #define MAX_LEVEL 256
2651 uint pos[MAX_LEVEL];
2669 if (str->reserve(
sizeof(
MY_XML_NODE), 2 * str->length() + 512))
2671 str->q_append((
const char*) node,
sizeof(
MY_XML_NODE));
2689 extern "C" int xml_enter(
MY_XML_PARSER *st,
const char *attr,
size_t len);
2691 int xml_enter(
MY_XML_PARSER *st,
const char *attr,
size_t len)
2694 uint numnodes= data->pxml->length() /
sizeof(
MY_XML_NODE);
2697 node.parent= data->parent;
2698 data->parent= numnodes;
2699 DBUG_ASSERT(data->level <= MAX_LEVEL);
2700 data->pos[data->level]= numnodes;
2701 if (data->level < MAX_LEVEL)
2702 node.level= data->level++;
2704 return MY_XML_ERROR;
2705 node.type= st->current_node_type;
2707 node.end= attr + len;
2708 return append_node(data->pxml, &node) ? MY_XML_ERROR : MY_XML_OK;
2724 extern "C" int xml_value(
MY_XML_PARSER *st,
const char *attr,
size_t len);
2726 int xml_value(
MY_XML_PARSER *st,
const char *attr,
size_t len)
2731 node.parent= data->parent;
2732 node.level= data->level;
2733 node.type= MY_XML_NODE_TEXT;
2735 node.end= attr + len;
2736 return append_node(data->pxml, &node) ? MY_XML_ERROR : MY_XML_OK;
2752 extern "C" int xml_leave(
MY_XML_PARSER *st,
const char *attr,
size_t len);
2754 int xml_leave(
MY_XML_PARSER *st,
const char *attr,
size_t len)
2757 DBUG_ASSERT(data->level > 0);
2761 data->parent= nodes[data->parent].parent;
2762 nodes+= data->pos[data->level];
2763 nodes->tagend= st->cur;
2785 parsed_xml_buf->length(0);
2788 my_xml_parser_create(&p);
2789 p.flags= MY_XML_FLAG_RELATIVE_NAMES | MY_XML_FLAG_SKIP_TEXT_NORMALIZATION;
2791 user_data.pxml= parsed_xml_buf;
2792 user_data.parent= 0;
2793 my_xml_set_enter_handler(&p, xml_enter);
2794 my_xml_set_value_handler(&p, xml_value);
2795 my_xml_set_leave_handler(&p, xml_leave);
2796 my_xml_set_user_data(&p, (
void*) &user_data);
2799 p.current_node_type= MY_XML_NODE_TAG;
2800 xml_enter(&p, raw_xml->ptr(), 0);
2803 if ((rc= my_xml_parse(&p, raw_xml->ptr(), raw_xml->length())) != MY_XML_OK)
2806 my_snprintf(buf,
sizeof(buf)-1,
"parse error at line %d pos %lu: %s",
2807 my_xml_error_lineno(&p) + 1,
2808 (ulong) my_xml_error_pos(&p) + 1,
2809 my_xml_error_string(&p));
2810 push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
2812 ER(ER_WRONG_VALUE),
"XML", buf);
2814 my_xml_parser_free(&p);
2816 return rc == MY_XML_OK ? parsed_xml_buf : 0;
2820 String *Item_func_xml_extractvalue::val_str(
String *str)
2826 if (!nodeset_func ||
2827 !(res= args[0]->val_str(str)) ||
2828 !parse_xml(res, &pxml) ||
2829 !(res= nodeset_func->val_str(&tmp_value)))
2840 String *res, *nodeset, *rep;
2845 if (!nodeset_func ||
2846 !(res= args[0]->val_str(str)) ||
2847 !(rep= args[2]->val_str(&tmp_value3)) ||
2848 !parse_xml(res, &pxml) ||
2849 !(nodeset= nodeset_func->val_nodeset(&tmp_value2)))
2860 if (fltend - fltbeg != 1)
2866 nodebeg+= fltbeg->num;
2868 if (!nodebeg->level)
2878 tmp_value.length(0);
2879 tmp_value.set_charset(collation.collation);
2880 uint offs= nodebeg->type == MY_XML_NODE_TAG ? 1 : 0;
2881 tmp_value.append(res->ptr(), nodebeg->beg - res->ptr() - offs);
2882 tmp_value.append(rep->ptr(), rep->length());
2883 const char *end= nodebeg->tagend + offs;
2884 tmp_value.append(end, res->ptr() + res->length() - end);