Below is the list of changes that have just been committed into a local
5.1 repository of bar. When bar does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet
1.2365 06/12/27 18:14:28 bar@stripped +3 -0
Bug#24747 XPath error with the node name "Text"
sql/item_xmlfunc.cc
1.23 06/12/27 18:14:24 bar@stripped +76 -16
Bug#24747 XPath error with the node name "Text"
Problem: keywords, nodetype names and axis names
didn't work in node name context.
Fix:
1. Changes in lexem scanner behaviour when an identifier has been read:
- search through axis names and return MY_XPATH_AXIS_xxx only
when identifier is followed by two semicolons. Don't check axis
names and return MY_XPATH_IDENT of not followed by two semicolons.
- search through nodetype names and return MY_XPATH_LEX_NODETYPE
only when identifier is followed by left parenthesis.
Don't check nodetype names and return MY_XPATH_LEX_IDENT when
not followed by parenthesis
2. Change in syntax analizer: QName scanner now accepts keywords
AND, OR, MOD, DIV as valid node names.
mysql-test/t/xml.test
1.19 06/12/27 18:14:24 bar@stripped +38 -0
Adding test case
mysql-test/r/xml.result
1.20 06/12/27 18:14:24 bar@stripped +75 -0
Adding test case
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: bar
# Host: bar.myoffice.izhnet.ru
# Root: /home/bar/mysql-5.1.b24747
--- 1.19/mysql-test/r/xml.result 2006-10-23 14:17:49 +05:00
+++ 1.20/mysql-test/r/xml.result 2006-12-27 18:14:24 +04:00
@@ -809,3 +809,78 @@
select ExtractValue(@xml, "/entry[(50<=pt)]/id");
ExtractValue(@xml, "/entry[(50<=pt)]/id")
pt50
+select ExtractValue('<a><b><Text>test</Text></b></a>','/a/b/Text');
+ExtractValue('<a><b><Text>test</Text></b></a>','/a/b/Text')
+test
+select ExtractValue('<a><b><comment>test</comment></b></a>','/a/b/comment');
+ExtractValue('<a><b><comment>test</comment></b></a>','/a/b/comment')
+test
+select ExtractValue('<a><b><node>test</node></b></a>','/a/b/node');
+ExtractValue('<a><b><node>test</node></b></a>','/a/b/node')
+test
+select ExtractValue('<a><b><processing-instruction>test</processing-instruction></b></a>','/a/b/processing-instruction');
+ExtractValue('<a><b><processing-instruction>test</processing-instruction></b></a>','/a/b/processing-instruction')
+test
+select ExtractValue('<a><and>test</and></a>', '/a/and');
+ExtractValue('<a><and>test</and></a>', '/a/and')
+test
+select ExtractValue('<a><or>test</or></a>', '/a/or');
+ExtractValue('<a><or>test</or></a>', '/a/or')
+test
+select ExtractValue('<a><mod>test</mod></a>', '/a/mod');
+ExtractValue('<a><mod>test</mod></a>', '/a/mod')
+test
+select ExtractValue('<a><div>test</div></a>', '/a/div');
+ExtractValue('<a><div>test</div></a>', '/a/div')
+test
+select ExtractValue('<a><and:and>test</and:and></a>', '/a/and:and');
+ExtractValue('<a><and:and>test</and:and></a>', '/a/and:and')
+test
+select ExtractValue('<a><or:or>test</or:or></a>', '/a/or:or');
+ExtractValue('<a><or:or>test</or:or></a>', '/a/or:or')
+test
+select ExtractValue('<a><mod:mod>test</mod:mod></a>', '/a/mod:mod');
+ExtractValue('<a><mod:mod>test</mod:mod></a>', '/a/mod:mod')
+test
+select ExtractValue('<a><div:div>test</div:div></a>', '/a/div:div');
+ExtractValue('<a><div:div>test</div:div></a>', '/a/div:div')
+test
+select ExtractValue('<a><ancestor>test</ancestor></a>', '/a/ancestor');
+ExtractValue('<a><ancestor>test</ancestor></a>', '/a/ancestor')
+test
+select ExtractValue('<a><ancestor-or-self>test</ancestor-or-self></a>', '/a/ancestor-or-self');
+ExtractValue('<a><ancestor-or-self>test</ancestor-or-self></a>', '/a/ancestor-or-self')
+test
+select ExtractValue('<a><attribute>test</attribute></a>', '/a/attribute');
+ExtractValue('<a><attribute>test</attribute></a>', '/a/attribute')
+test
+select ExtractValue('<a><child>test</child></a>', '/a/child');
+ExtractValue('<a><child>test</child></a>', '/a/child')
+test
+select ExtractValue('<a><descendant>test</descendant></a>', '/a/descendant');
+ExtractValue('<a><descendant>test</descendant></a>', '/a/descendant')
+test
+select ExtractValue('<a><descendant-or-self>test</descendant-or-self></a>', '/a/descendant-or-self');
+ExtractValue('<a><descendant-or-self>test</descendant-or-self></a>', '/a/descendant-or-self')
+test
+select ExtractValue('<a><following>test</following></a>', '/a/following');
+ExtractValue('<a><following>test</following></a>', '/a/following')
+test
+select ExtractValue('<a><following-sibling>test</following-sibling></a>', '/a/following-sibling');
+ExtractValue('<a><following-sibling>test</following-sibling></a>', '/a/following-sibling')
+test
+select ExtractValue('<a><namespace>test</namespace></a>', '/a/namespace');
+ExtractValue('<a><namespace>test</namespace></a>', '/a/namespace')
+test
+select ExtractValue('<a><parent>test</parent></a>', '/a/parent');
+ExtractValue('<a><parent>test</parent></a>', '/a/parent')
+test
+select ExtractValue('<a><preceding>test</preceding></a>', '/a/preceding');
+ExtractValue('<a><preceding>test</preceding></a>', '/a/preceding')
+test
+select ExtractValue('<a><preceding-sibling>test</preceding-sibling></a>', '/a/preceding-sibling');
+ExtractValue('<a><preceding-sibling>test</preceding-sibling></a>', '/a/preceding-sibling')
+test
+select ExtractValue('<a><self>test</self></a>', '/a/self');
+ExtractValue('<a><self>test</self></a>', '/a/self')
+test
--- 1.18/mysql-test/t/xml.test 2006-10-23 14:17:49 +05:00
+++ 1.19/mysql-test/t/xml.test 2006-12-27 18:14:24 +04:00
@@ -406,3 +406,41 @@
select ExtractValue(@xml, "/entry[(50>=pt)]/id");
select ExtractValue(@xml, "/entry[(50<pt)]/id");
select ExtractValue(@xml, "/entry[(50<=pt)]/id");
+
+#
+# Bug#24747 XPath error with the node name "Text"
+#
+#
+# Test nodetypes in node name context
+#
+select ExtractValue('<a><b><Text>test</Text></b></a>','/a/b/Text');
+select ExtractValue('<a><b><comment>test</comment></b></a>','/a/b/comment');
+select ExtractValue('<a><b><node>test</node></b></a>','/a/b/node');
+select ExtractValue('<a><b><processing-instruction>test</processing-instruction></b></a>','/a/b/processing-instruction');
+#
+# Test keywords in node name contexts
+#
+select ExtractValue('<a><and>test</and></a>', '/a/and');
+select ExtractValue('<a><or>test</or></a>', '/a/or');
+select ExtractValue('<a><mod>test</mod></a>', '/a/mod');
+select ExtractValue('<a><div>test</div></a>', '/a/div');
+select ExtractValue('<a><and:and>test</and:and></a>', '/a/and:and');
+select ExtractValue('<a><or:or>test</or:or></a>', '/a/or:or');
+select ExtractValue('<a><mod:mod>test</mod:mod></a>', '/a/mod:mod');
+select ExtractValue('<a><div:div>test</div:div></a>', '/a/div:div');
+#
+# Test axis names in node name context
+#
+select ExtractValue('<a><ancestor>test</ancestor></a>', '/a/ancestor');
+select ExtractValue('<a><ancestor-or-self>test</ancestor-or-self></a>', '/a/ancestor-or-self');
+select ExtractValue('<a><attribute>test</attribute></a>', '/a/attribute');
+select ExtractValue('<a><child>test</child></a>', '/a/child');
+select ExtractValue('<a><descendant>test</descendant></a>', '/a/descendant');
+select ExtractValue('<a><descendant-or-self>test</descendant-or-self></a>', '/a/descendant-or-self');
+select ExtractValue('<a><following>test</following></a>', '/a/following');
+select ExtractValue('<a><following-sibling>test</following-sibling></a>', '/a/following-sibling');
+select ExtractValue('<a><namespace>test</namespace></a>', '/a/namespace');
+select ExtractValue('<a><parent>test</parent></a>', '/a/parent');
+select ExtractValue('<a><preceding>test</preceding></a>', '/a/preceding');
+select ExtractValue('<a><preceding-sibling>test</preceding-sibling></a>', '/a/preceding-sibling');
+select ExtractValue('<a><self>test</self></a>', '/a/self');
--- 1.22/sql/item_xmlfunc.cc 2006-11-30 05:40:29 +04:00
+++ 1.23/sql/item_xmlfunc.cc 2006-12-27 18:14:24 +04:00
@@ -1047,12 +1047,12 @@
{MY_XPATH_LEX_OR , "or" , 2, 0 },
{MY_XPATH_LEX_DIV , "div" , 3, 0 },
{MY_XPATH_LEX_MOD , "mod" , 3, 0 },
-
- {MY_XPATH_LEX_NODETYPE, "comment" , 7, 0 },
- {MY_XPATH_LEX_NODETYPE, "text" , 4, 0 },
- {MY_XPATH_LEX_NODETYPE, "processing-instruction" , 22,0 },
- {MY_XPATH_LEX_NODETYPE, "node" , 4, 0 },
-
+ {0,NULL,0,0}
+};
+
+
+static struct my_xpath_keyword_names_st my_axis_names[]=
+{
{MY_XPATH_LEX_AXIS,"ancestor" , 8,MY_XPATH_AXIS_ANCESTOR },
{MY_XPATH_LEX_AXIS,"ancestor-or-self" ,16,MY_XPATH_AXIS_ANCESTOR_OR_SELF },
{MY_XPATH_LEX_AXIS,"attribute" , 9,MY_XPATH_AXIS_ATTRIBUTE },
@@ -1066,7 +1066,16 @@
{MY_XPATH_LEX_AXIS,"preceding" , 9,MY_XPATH_AXIS_PRECEDING },
{MY_XPATH_LEX_AXIS,"preceding-sibling" ,17,MY_XPATH_AXIS_PRECEDING_SIBLING },
{MY_XPATH_LEX_AXIS,"self" , 4,MY_XPATH_AXIS_SELF },
+ {0,NULL,0,0}
+};
+
+static struct my_xpath_keyword_names_st my_nodetype_names[]=
+{
+ {MY_XPATH_LEX_NODETYPE, "comment" , 7, 0 },
+ {MY_XPATH_LEX_NODETYPE, "text" , 4, 0 },
+ {MY_XPATH_LEX_NODETYPE, "processing-instruction" , 22,0 },
+ {MY_XPATH_LEX_NODETYPE, "node" , 4, 0 },
{0,NULL,0,0}
};
@@ -1081,11 +1090,14 @@
- Token type, on lookup success.
- MY_XPATH_LEX_IDENT, on lookup failure.
*/
-static int my_xpath_keyword(MY_XPATH *x, const char *beg, const char *end)
+static int
+my_xpath_keyword(MY_XPATH *x,
+ struct my_xpath_keyword_names_st *keyword_names,
+ const char *beg, const char *end)
{
struct my_xpath_keyword_names_st *k;
size_t length= end-beg;
- for (k= my_keyword_names; k->name; k++)
+ for (k= keyword_names; k->name; k++)
{
if (length == k->length && !strncasecmp(beg, k->name, length))
{
@@ -1371,15 +1383,32 @@
beg+= length) /* no op */;
lex->end= beg;
- // check if a function call
- if (*beg == '(' && (xpath->func= my_xpath_function(lex->beg, beg)))
+ if (beg < end)
{
- lex->term= MY_XPATH_LEX_FUNC;
- return;
+ if (*beg == '(')
+ {
+ /*
+ check if a function call, e.g.: count(/a/b)
+ or a nodetype test, e.g.: /a/b/text()
+ */
+ if ((xpath->func= my_xpath_function(lex->beg, beg)))
+ lex->term= MY_XPATH_LEX_FUNC;
+ else
+ lex->term= my_xpath_keyword(xpath, my_nodetype_names,
+ lex->beg, beg);
+ return;
+ }
+ // check if an axis specifier, e.g.: /a/b/child::*
+ else if (*beg == ':' && beg + 1 < end && beg[1] == ':')
+ {
+ lex->term= my_xpath_keyword(xpath, my_axis_names,
+ lex->beg, beg);
+ return;
+ }
}
-
// check if a keyword
- lex->term= my_xpath_keyword(xpath, lex->beg, beg);
+ lex->term= my_xpath_keyword(xpath, my_keyword_names,
+ lex->beg, beg);
return;
}
@@ -2334,6 +2363,36 @@
/*
+ Scan NCName.
+
+ SYNOPSYS
+
+ The keywords AND, OR, MOD, DIV are valid identitiers
+ when they are in identifier context:
+
+ SELECT
+ ExtractValue('<and><or><mod><div>VALUE</div></mod></or></and>',
+ '/and/or/mod/div')
+ -> VALUE
+
+ RETURN
+ 1 - success
+ 0 - failure
+*/
+
+static int
+my_xpath_parse_NCName(MY_XPATH *xpath)
+{
+ return
+ my_xpath_parse_term(xpath, MY_XPATH_LEX_IDENT) ||
+ my_xpath_parse_term(xpath, MY_XPATH_LEX_AND) ||
+ my_xpath_parse_term(xpath, MY_XPATH_LEX_OR) ||
+ my_xpath_parse_term(xpath, MY_XPATH_LEX_MOD) ||
+ my_xpath_parse_term(xpath, MY_XPATH_LEX_DIV) ? 1 : 0;
+}
+
+
+/*
QName grammar can be found in a separate document
http://www.w3.org/TR/REC-xml-names/#NT-QName
@@ -2341,16 +2400,17 @@
[7] Prefix ::= NCName
[8] LocalPart ::= NCName
*/
+
static int
my_xpath_parse_QName(MY_XPATH *xpath)
{
const char *beg;
- if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_IDENT))
+ if (!my_xpath_parse_NCName(xpath))
return 0;
beg= xpath->prevtok.beg;
if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_COLON))
return 1; /* Non qualified name */
- if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_IDENT))
+ if (!my_xpath_parse_NCName(xpath))
return 0;
xpath->prevtok.beg= beg;
return 1;
| Thread |
|---|
| • bk commit into 5.1 tree (bar:1.2365) BUG#24747 | bar | 27 Dec |