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@stripped, 2007-05-08 13:32:29+05:00, bar@stripped +3 -0
Bug#26518 XPath and variables problem
Problem: XPath variables didn't work.
Fix: adding variables support,
both user-defined and sp local variables are now supported by XPath.
mysql-test/r/xml.result@stripped, 2007-05-08 13:32:28+05:00, bar@stripped +115 -0
Adding test case
mysql-test/t/xml.test@stripped, 2007-05-08 13:32:28+05:00, bar@stripped +72 -0
Adding test case
sql/item_xmlfunc.cc@stripped, 2007-05-08 13:32:28+05:00, bar@stripped +66 -9
Adding variables support:
- SP variables with standard XPath syntax: $i
- User variables with non-standard syntax: $@i
# 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.b26518
--- 1.21/mysql-test/r/xml.result 2007-01-22 13:28:51 +04:00
+++ 1.22/mysql-test/r/xml.result 2007-05-08 13:32:28 +05:00
@@ -884,3 +884,118 @@
select ExtractValue('<a><self>test</self></a>', '/a/self');
ExtractValue('<a><self>test</self></a>', '/a/self')
test
+set @i=1;
+select
ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/b[$@i]');
+ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/b[$@i]')
+b1
+set @i=2;
+select
ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/b[$@i]');
+ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/b[$@i]')
+b2
+set @i=NULL;
+select
ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/b[$@i]');
+ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/b[$@i]')
+
+CREATE PROCEDURE spxml(xml VARCHAR(128))
+BEGIN
+DECLARE c INT;
+DECLARE i INT DEFAULT 1;
+SET c= ExtractValue(xml,'count(/a/b)');
+SET @i= c;
+WHILE i <= c DO
+BEGIN
+SELECT i, @i, ExtractValue(xml,'/a/b[$i]'), ExtractValue(xml,'/a/b[$@i]');
+SET i= i + 1;
+SET @i= @i - 1;
+END;
+END WHILE;
+END|
+call
spxml('<a><b>b1</b><b>b2</b><b>b3</b></a>');
+i @i ExtractValue(xml,'/a/b[$i]') ExtractValue(xml,'/a/b[$@i]')
+1 3 b1 b3
+i @i ExtractValue(xml,'/a/b[$i]') ExtractValue(xml,'/a/b[$@i]')
+2 2 b2 b2
+i @i ExtractValue(xml,'/a/b[$i]') ExtractValue(xml,'/a/b[$@i]')
+3 1 b3 b1
+drop procedure spxml;
+Multiple matches, but no index specification
+SELECT
ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/b');
+ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/b')
+b1 b2
+No matches
+SELECT
ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/c');
+ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/c')
+
+Index out of range
+SELECT
ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/b[-1]');
+ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/b[-1]')
+
+SELECT
ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/b[10]');
+ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/b[10]')
+
+With string-to-number conversion
+SELECT
ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/b["1"]');
+ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/b["1"]')
+b1
+SELECT
ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/b["1 and
string"]');
+ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/b["1 and
string"]')
+b1
+Warnings:
+Warning 1292 Truncated incorrect INTEGER value: '1 and string"]'
+Warning 1292 Truncated incorrect INTEGER value: '1 and string"]'
+SELECT
ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/b["string
and 1"]');
+ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/b["string
and 1"]')
+
+Warnings:
+Warning 1292 Truncated incorrect INTEGER value: 'string and 1"]'
+Warning 1292 Truncated incorrect INTEGER value: 'string and 1"]'
+SELECT
ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/b["string"]');
+ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/b["string"]')
+
+Warnings:
+Warning 1292 Truncated incorrect INTEGER value: 'string"]'
+Warning 1292 Truncated incorrect INTEGER value: 'string"]'
+String-to-number conversion from a user variable
+SET @i='1';
+SELECT
ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/b[$@i]');
+ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/b[$@i]')
+b1
+SET @i='1 and string';
+SELECT
ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/b[$@i]');
+ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/b[$@i]')
+b1
+SET @i='string and 1';
+SELECT
ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/b[$@i]');
+ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/b[$@i]')
+
+SET @i='string';
+SELECT
ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/b[$@i]');
+ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/b[$@i]')
+
+String-to-number conversion with a CHAR SP variable
+CREATE PROCEDURE spxml(xml VARCHAR(128), i CHAR(16))
+BEGIN
+SELECT ExtractValue(xml,'/a/b[$i]');
+END|
+CALL spxml('<a><b>b1</b><b>b2</b></a>', '1');
+ExtractValue(xml,'/a/b[$i]')
+b1
+CALL spxml('<a><b>b1</b><b>b2</b></a>', '1 and
string');
+ExtractValue(xml,'/a/b[$i]')
+b1
+Warnings:
+Warning 1292 Truncated incorrect INTEGER value: '1 and string '
+Warning 1292 Truncated incorrect INTEGER value: '1 and string '
+CALL spxml('<a><b>b1</b><b>b2</b></a>', 'string and
1');
+ExtractValue(xml,'/a/b[$i]')
+
+Warnings:
+Warning 1292 Truncated incorrect INTEGER value: 'string and 1 '
+Warning 1292 Truncated incorrect INTEGER value: 'string and 1 '
+CALL spxml('<a><b>b1</b><b>b2</b></a>', 'string');
+ExtractValue(xml,'/a/b[$i]')
+
+Warnings:
+Warning 1292 Truncated incorrect INTEGER value: 'string '
+Warning 1292 Truncated incorrect INTEGER value: 'string '
+DROP PROCEDURE spxml;
--- 1.19/mysql-test/t/xml.test 2006-12-27 18:14:24 +04:00
+++ 1.20/mysql-test/t/xml.test 2007-05-08 13:32:28 +05:00
@@ -444,3 +444,75 @@
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');
+
+#
+# Bug#26518 XPath and variables problem
+# Check with user defined variables
+#
+set @i=1;
+select
ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/b[$@i]');
+set @i=2;
+select
ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/b[$@i]');
+set @i=NULL;
+select
ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/b[$@i]');
+
+#
+# Check variables in a stored procedure - both local and user variables
+# Make sure that SP and local variables with the same name work together.
+#
+DELIMITER |;
+CREATE PROCEDURE spxml(xml VARCHAR(128))
+BEGIN
+ DECLARE c INT;
+ DECLARE i INT DEFAULT 1;
+ SET c= ExtractValue(xml,'count(/a/b)');
+ SET @i= c;
+ WHILE i <= c DO
+ BEGIN
+ SELECT i, @i, ExtractValue(xml,'/a/b[$i]'), ExtractValue(xml,'/a/b[$@i]');
+ SET i= i + 1;
+ SET @i= @i - 1;
+ END;
+ END WHILE;
+END|
+DELIMITER ;|
+
+call
spxml('<a><b>b1</b><b>b2</b><b>b3</b></a>');
+drop procedure spxml;
+
+#
+# Additional tests for bug#26518
+--echo Multiple matches, but no index specification
+SELECT
ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/b');
+--echo No matches
+SELECT
ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/c');
+--echo Index out of range
+SELECT
ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/b[-1]');
+SELECT
ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/b[10]');
+--echo With string-to-number conversion
+SELECT
ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/b["1"]');
+SELECT
ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/b["1 and
string"]');
+SELECT
ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/b["string
and 1"]');
+SELECT
ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/b["string"]');
+--echo String-to-number conversion from a user variable
+SET @i='1';
+SELECT
ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/b[$@i]');
+SET @i='1 and string';
+SELECT
ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/b[$@i]');
+SET @i='string and 1';
+SELECT
ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/b[$@i]');
+SET @i='string';
+SELECT
ExtractValue('<a><b>b1</b><b>b2</b></a>','/a/b[$@i]');
+
+--echo String-to-number conversion with a CHAR SP variable
+DELIMITER |;
+CREATE PROCEDURE spxml(xml VARCHAR(128), i CHAR(16))
+BEGIN
+ SELECT ExtractValue(xml,'/a/b[$i]');
+END|
+DELIMITER ;|
+CALL spxml('<a><b>b1</b><b>b2</b></a>', '1');
+CALL spxml('<a><b>b1</b><b>b2</b></a>', '1 and
string');
+CALL spxml('<a><b>b1</b><b>b2</b></a>', 'string and
1');
+CALL spxml('<a><b>b1</b><b>b2</b></a>', 'string');
+DROP PROCEDURE spxml;
--- 1.26/sql/item_xmlfunc.cc 2007-02-24 14:43:10 +04:00
+++ 1.27/sql/item_xmlfunc.cc 2007-05-08 13:32:28 +05:00
@@ -19,7 +19,7 @@
#include "mysql_priv.h"
#include "my_xml.h"
-
+#include "sp_pcontext.h"
/*
TODO: future development directions:
@@ -2412,21 +2412,78 @@
}
-/*
+/**
Scan Variable reference
- SYNOPSYS
+ @details Implements parsing of two syntax structures:
- [36] VariableReference ::= '$' QName
- RETURN
- 1 - success
- 0 - failure
+ 1. Standard XPath syntax [36], for SP variables:
+
+ VariableReference ::= '$' QName
+
+ Finds a SP variable with the given name.
+ If outside of a SP context, or variable with
+ the given name doesn't exists, then error is returned.
+
+ 2. Non-standard syntax - MySQL extension for user variables:
+
+ VariableReference ::= '$' '@' QName
+
+ Item, corresponding to the variable, is returned
+ in xpath->item in both cases.
+
+ @param xpath pointer to XPath structure
+
+ @return Operation status
+ @retval 1 Success
+ @retval 0 Failure
*/
+
static int
my_xpath_parse_VariableReference(MY_XPATH *xpath)
{
- return my_xpath_parse_term(xpath, MY_XPATH_LEX_DOLLAR) &&
- my_xpath_parse_term(xpath, MY_XPATH_LEX_IDENT);
+ LEX_STRING name;
+ int user_var;
+ const char *dollar_pos;
+ if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_DOLLAR) ||
+ (!(dollar_pos= xpath->prevtok.beg)) ||
+ (!((user_var= my_xpath_parse_term(xpath, MY_XPATH_LEX_AT) &&
+ my_xpath_parse_term(xpath, MY_XPATH_LEX_IDENT))) &&
+ !my_xpath_parse_term(xpath, MY_XPATH_LEX_IDENT)))
+ return 0;
+
+ name.length= xpath->prevtok.end - xpath->prevtok.beg;
+ name.str= (char*) xpath->prevtok.beg;
+
+ if (user_var)
+ xpath->item= new Item_func_get_user_var(name);
+ else
+ {
+ sp_variable_t *spv;
+ sp_pcontext *spc;
+ LEX *lex;
+ if ((lex= current_thd->lex) &&
+ (spc= lex->spcont) &&
+ (spv= spc->find_variable(&name)))
+ {
+ Item_splocal *splocal= new Item_splocal(name, spv->offset, spv->type, 0);
+#ifndef DBUG_OFF
+ if (splocal)
+ splocal->m_sp= lex->sphead;
+#endif
+ xpath->item= (Item*) splocal;
+ }
+ else
+ {
+ xpath->item= NULL;
+ DBUG_ASSERT(xpath->query.end > dollar_pos);
+ uint len= xpath->query.end - dollar_pos;
+ set_if_smaller(len, 32);
+ my_printf_error(ER_UNKNOWN_ERROR, "Unknown XPATH variable at: '%.*s'",
+ MYF(0), len, dollar_pos);
+ }
+ }
+ return xpath->item ? 1 : 0;
}
| Thread |
|---|
| • bk commit into 5.1 tree (bar:1.2481) BUG#26518 | bar | 8 May |