List:Commits« Previous MessageNext Message »
From:bar Date:December 27 2006 3:14pm
Subject:bk commit into 5.1 tree (bar:1.2365) BUG#24747
View as plain text  
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#24747bar27 Dec