diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc
index 033c55707fc..d2357aa10ec 100644
--- a/client/mysqlbinlog.cc
+++ b/client/mysqlbinlog.cc
@@ -682,8 +682,16 @@ Begin_load_query event for file_id: %u\n", exlq->file_id);
end:
rec_count++;
+ /*
+ Destroy the log_event object. If reading from a remote host,
+ set the temp_buf to NULL so that memory isn't freed twice.
+ */
if (ev)
+ {
+ if (remote_opt)
+ ev->temp_buf= 0;
delete ev;
+ }
DBUG_RETURN(0);
}
@@ -1172,6 +1180,12 @@ could be out of memory");
error= 1;
goto err;
}
+ /*
+ If reading from a remote host, ensure the temp_buf for the
+ Log_event class is pointing to the incoming stream.
+ */
+ if (remote_opt)
+ ev->register_temp_buf((char*) net->read_pos + 1);
Log_event_type type= ev->get_type_code();
if (glob_description_event->binlog_version >= 3 ||
diff --git a/mysql-test/extra/rpl_tests/rpl_loaddata.test b/mysql-test/extra/rpl_tests/rpl_loaddata.test
index 111b66ff7fe..dea83f65898 100644
--- a/mysql-test/extra/rpl_tests/rpl_loaddata.test
+++ b/mysql-test/extra/rpl_tests/rpl_loaddata.test
@@ -15,6 +15,7 @@
# Last_slave_errno in SHOW SLAVE STATUS (1st and 3rd commands did not: bug 986)
-- source include/master-slave.inc
+source include/have_innodb.inc;
connection slave;
reset master;
@@ -156,4 +157,15 @@ drop table t2;
connection master;
drop table t2;
drop table t1;
+
+# BUG#17233 LOAD DATA INFILE: failure causes mysqld dbug_assert, binlog not flushed
+CREATE TABLE t1 (word CHAR(20) NOT NULL PRIMARY KEY) ENGINE=INNODB;
+
+--error ER_DUP_ENTRY_WITH_KEY_NAME
+LOAD DATA INFILE "../std_data_ln/words.dat" INTO TABLE t1;
+
+--disable warnings
+DROP TABLE IF EXISTS t1;
+--enable warnings
+
# End of 4.1 tests
diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl
index df39be15f05..50edcecbfa9 100755
--- a/mysql-test/mysql-test-run.pl
+++ b/mysql-test/mysql-test-run.pl
@@ -1804,6 +1804,18 @@ sub environment_setup () {
$ENV{'CHARSETSDIR'}= $path_charsetsdir;
$ENV{'UMASK'}= "0660"; # The octal *string*
$ENV{'UMASK_DIR'}= "0770"; # The octal *string*
+
+ #
+ # MySQL tests can produce output in various character sets
+ # (especially, ctype_xxx.test). To avoid confusing Perl
+ # with output which is incompatible with the current locale
+ # settings, we reset the current values of LC_ALL and LC_CTYPE to "C".
+ # For details, please see
+ # Bug#27636 tests fails if LC_* variables set to *_*.UTF-8
+ #
+ $ENV{'LC_ALL'}= "C";
+ $ENV{'LC_CTYPE'}= "C";
+
$ENV{'LC_COLLATE'}= "C";
$ENV{'USE_RUNNING_SERVER'}= $opt_extern;
$ENV{'MYSQL_TEST_DIR'}= $glob_mysql_test_dir;
@@ -3851,13 +3863,15 @@ sub mysqld_arguments ($$$$) {
}
else
{
- mtr_add_arg($args, "%s--master-user=root", $prefix);
- mtr_add_arg($args, "%s--master-connect-retry=1", $prefix);
- mtr_add_arg($args, "%s--master-host=127.0.0.1", $prefix);
- mtr_add_arg($args, "%s--master-password=", $prefix);
- mtr_add_arg($args, "%s--master-port=%d", $prefix,
- $master->[0]->{'port'}); # First master
-
+ if ($mysql_version_id < 50200)
+ {
+ mtr_add_arg($args, "%s--master-user=root", $prefix);
+ mtr_add_arg($args, "%s--master-connect-retry=1", $prefix);
+ mtr_add_arg($args, "%s--master-host=127.0.0.1", $prefix);
+ mtr_add_arg($args, "%s--master-password=", $prefix);
+ mtr_add_arg($args, "%s--master-port=%d", $prefix,
+ $master->[0]->{'port'}); # First master
+ }
my $slave_server_id= 2 + $idx;
my $slave_rpl_rank= $slave_server_id;
mtr_add_arg($args, "%s--server-id=%d", $prefix, $slave_server_id);
diff --git a/mysql-test/r/rpl_critical_errors.result b/mysql-test/r/rpl_critical_errors.result
deleted file mode 100644
index bcc53565084..00000000000
--- a/mysql-test/r/rpl_critical_errors.result
+++ /dev/null
@@ -1 +0,0 @@
-Turn on parsing to run this test
diff --git a/mysql-test/r/rpl_loaddata.result b/mysql-test/r/rpl_loaddata.result
index cabc20b7057..680796a4be6 100644
--- a/mysql-test/r/rpl_loaddata.result
+++ b/mysql-test/r/rpl_loaddata.result
@@ -86,3 +86,7 @@ ERROR 23000: Duplicate entry '2003-03-22' for key 'day'
drop table t2;
drop table t2;
drop table t1;
+CREATE TABLE t1 (word CHAR(20) NOT NULL PRIMARY KEY) ENGINE=INNODB;
+LOAD DATA INFILE "../std_data_ln/words.dat" INTO TABLE t1;
+ERROR 23000: Duplicate entry 'Aarhus' for key 'PRIMARY'
+DROP TABLE IF EXISTS t1;
diff --git a/mysql-test/r/rpl_row_mysqlbinlog.result b/mysql-test/r/rpl_row_mysqlbinlog.result
index c9f46e73cfd..e2df1459ac0 100644
--- a/mysql-test/r/rpl_row_mysqlbinlog.result
+++ b/mysql-test/r/rpl_row_mysqlbinlog.result
@@ -190,6 +190,75 @@ DELIMITER ;
ROLLBACK /* added by mysqlbinlog */;
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+--- Test 4 Second Remote test --
+DROP TABLE t1;
+DROP TABLE t2;
+DROP TABLE t3;
+stop slave;
+reset master;
+reset slave;
+start slave;
+SELECT COUNT(*) from t1;
+COUNT(*)
+352
+SELECT COUNT(*) from t2;
+COUNT(*)
+500
+SELECT COUNT(*) from t3;
+COUNT(*)
+500
+SELECT * FROM t1 ORDER BY word LIMIT 5;
+word
+Aarhus
+Aarhus
+Aarhus
+Aarhus
+Aarhus
+SELECT * FROM t2 ORDER BY id LIMIT 5;
+id
+1
+2
+3
+4
+5
+SELECT c1, c3, c4, c5 FROM t3 ORDER BY c1 LIMIT 5;
+c1 c3 c4 c5
+1 2006-02-22 00:00:00 Tested in Texas 2.2
+2 2006-02-22 00:00:00 Tested in Texas 4.4
+3 2006-02-22 00:00:00 Tested in Texas 6.6
+4 2006-02-22 00:00:00 Tested in Texas 8.8
+5 2006-02-22 00:00:00 Tested in Texas 11
+SELECT COUNT(*) from t1;
+COUNT(*)
+352
+SELECT COUNT(*) from t2;
+COUNT(*)
+500
+SELECT COUNT(*) from t3;
+COUNT(*)
+500
+SELECT * FROM t1 ORDER BY word LIMIT 5;
+word
+Aarhus
+Aarhus
+Aarhus
+Aarhus
+Aarhus
+SELECT * FROM t2 ORDER BY id LIMIT 5;
+id
+1
+2
+3
+4
+5
+SELECT c1, c3, c4, c5 FROM t3 ORDER BY c1 LIMIT 5;
+c1 c3 c4 c5
+1 2006-02-22 00:00:00 Tested in Texas 2.2
+2 2006-02-22 00:00:00 Tested in Texas 4.4
+3 2006-02-22 00:00:00 Tested in Texas 6.6
+4 2006-02-22 00:00:00 Tested in Texas 8.8
+5 2006-02-22 00:00:00 Tested in Texas 11
+
--- Test 5 LOAD DATA --
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
@@ -273,4 +342,11 @@ HEX(f)
835C
--- Test cleanup --
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (a INT NOT NULL KEY, b INT);
+INSERT INTO t1 VALUES(1,1);
+SELECT * FROM t1;
+a b
+1 1
+FLUSH LOGS;
DROP TABLE IF EXISTS t1, t2, t3, t04, t05, t4, t5;
diff --git a/mysql-test/r/xml.result b/mysql-test/r/xml.result
index 236c50774bd..f71b8cadabb 100644
--- a/mysql-test/r/xml.result
+++ b/mysql-test/r/xml.result
@@ -547,6 +547,13 @@ UpdateXML(@xml, '/a/b/@bb2', '')
select UpdateXML(@xml, '/a/b/@bb2', 'bb3="bb3"');
UpdateXML(@xml, '/a/b/@bb2', 'bb3="bb3"')
bb
+select updatexml('
',
+'/','1 | 2 |
') as upd1;
+upd1
+1 | 2 |
+select updatexml('', '/', '') as upd2;
+upd2
+
SET @xml= 'lesser wombat';
select extractvalue(@xml,'order/clerk');
extractvalue(@xml,'order/clerk')
@@ -884,3 +891,124 @@ test
select ExtractValue('test', '/a/self');
ExtractValue('test', '/a/self')
test
+set @i=1;
+select ExtractValue('b1b2','/a/b[$@i]');
+ExtractValue('b1b2','/a/b[$@i]')
+b1
+set @i=2;
+select ExtractValue('b1b2','/a/b[$@i]');
+ExtractValue('b1b2','/a/b[$@i]')
+b2
+set @i=NULL;
+select ExtractValue('b1b2','/a/b[$@i]');
+ExtractValue('b1b2','/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('b1b2b3');
+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('b1b2','/a/b');
+ExtractValue('b1b2','/a/b')
+b1 b2
+No matches
+SELECT ExtractValue('b1b2','/a/c');
+ExtractValue('b1b2','/a/c')
+
+Index out of range
+SELECT ExtractValue('b1b2','/a/b[-1]');
+ExtractValue('b1b2','/a/b[-1]')
+
+SELECT ExtractValue('b1b2','/a/b[10]');
+ExtractValue('b1b2','/a/b[10]')
+
+With string-to-number conversion
+SELECT ExtractValue('b1b2','/a/b["1"]');
+ExtractValue('b1b2','/a/b["1"]')
+b1
+SELECT ExtractValue('b1b2','/a/b["1 and string"]');
+ExtractValue('b1b2','/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('b1b2','/a/b["string and 1"]');
+ExtractValue('b1b2','/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('b1b2','/a/b["string"]');
+ExtractValue('b1b2','/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('b1b2','/a/b[$@i]');
+ExtractValue('b1b2','/a/b[$@i]')
+b1
+SET @i='1 and string';
+SELECT ExtractValue('b1b2','/a/b[$@i]');
+ExtractValue('b1b2','/a/b[$@i]')
+b1
+SET @i='string and 1';
+SELECT ExtractValue('b1b2','/a/b[$@i]');
+ExtractValue('b1b2','/a/b[$@i]')
+
+SET @i='string';
+SELECT ExtractValue('b1b2','/a/b[$@i]');
+ExtractValue('b1b2','/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('b1b2', '1');
+ExtractValue(xml,'/a/b[$i]')
+b1
+CALL spxml('b1b2', '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('b1b2', '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('b1b2', 'string');
+ExtractValue(xml,'/a/b[$i]')
+
+Warnings:
+Warning 1292 Truncated incorrect INTEGER value: 'string '
+Warning 1292 Truncated incorrect INTEGER value: 'string '
+DROP PROCEDURE spxml;
+select UpdateXML('a',repeat('a b ',1000),'');
+ERROR HY000: XPATH syntax error: 'b a b a b a b a b a b a b a b a '
+select ExtractValue('a', '/a[@x=@y0123456789_0123456789_0123456789_0123456789]');
+ERROR HY000: XPATH error: comparison of two nodesets is not supported: '=@y0123456789_0123456789_0123456'
+select ExtractValue('a', '/a[@x=$y0123456789_0123456789_0123456789_0123456789]');
+ERROR HY000: Unknown XPATH variable at: '$y0123456789_0123456789_01234567'
diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def
index e2a0b30c592..c584f448a34 100644
--- a/mysql-test/t/disabled.def
+++ b/mysql-test/t/disabled.def
@@ -25,11 +25,10 @@ rpl_ndb_circular_simplex : BUG#27972 2007-04-20 mats Slave cannot start where it
rpl_ndb_2innodb : BUG#19227 2006-04-20 pekka pk delete apparently not replicated
rpl_ndb_2myisam : BUG#19227 Seems to pass currently
rpl_ndb_dd_partitions : BUG#19259 2006-04-21 rpl_ndb_dd_partitions fails on s/AMD
-rpl_ndb_ddl : BUG#18946 result file needs update + test needs to checked
rpl_ddl : BUG#26418 2007-03-01 mleich Slave out of sync after CREATE/DROP TEMPORARY TABLE + ROLLBACK on master
rpl_ndb_innodb2ndb : Bug #19710 Cluster replication to partition table fails on DELETE FROM statement
rpl_ndb_myisam2ndb : Bug #19710 Cluster replication to partition table fails on DELETE FROM statement
-rpl_row_blob_innodb : BUG#18980 2006-04-10 kent Test fails randomly
+#rpl_row_blob_innodb : BUG#18980 2006-04-10 kent Test fails randomly
synchronization : Bug#24529 Test 'synchronization' fails on Mac pushbuild; Also on Linux 64 bit.
# the below testcase have been reworked to avoid the bug, test contains comment, keep bug open
diff --git a/mysql-test/t/rpl_ndb_ddl.test b/mysql-test/t/rpl_ndb_ddl.test
index ca7a4ce4968..66db755de15 100644
--- a/mysql-test/t/rpl_ndb_ddl.test
+++ b/mysql-test/t/rpl_ndb_ddl.test
@@ -24,6 +24,7 @@
#
--source include/master-slave.inc
+--source include/have_binlog_format_row.inc
--source include/have_ndb.inc
let $engine_type= NDB;
let $temp_engine_type= MEMORY;
diff --git a/mysql-test/t/rpl_row_mysqlbinlog.test b/mysql-test/t/rpl_row_mysqlbinlog.test
index 1a5dd281ae1..dd46d64f684 100644
--- a/mysql-test/t/rpl_row_mysqlbinlog.test
+++ b/mysql-test/t/rpl_row_mysqlbinlog.test
@@ -183,67 +183,67 @@ select "--- Test 3 First Remote test --" as "";
--exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001
# This part is disabled due to bug #17654
-################### Start Bug 17654 ######################
-#--disable_query_log
-#select "--- Test 4 Second Remote test --" as "";
-#--enable_query_log
-#--exec $MYSQL_BINLOG --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 > $MYSQLTEST_VARDIR/tmp/remote.sql
-#--exec $MYSQL_BINLOG --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000002 >> $MYSQLTEST_VARDIR/tmp/remote.sql
+--disable_query_log
+select "--- Test 4 Second Remote test --" as "";
+--enable_query_log
+--exec $MYSQL_BINLOG --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 > $MYSQLTEST_VARDIR/tmp/remote.sql
+
+--exec $MYSQL_BINLOG --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000002 >> $MYSQLTEST_VARDIR/tmp/remote.sql
# Now that we have our file, lets get rid of the current database.
# Cleanup the master and the slave and try to recreate.
-#DROP TABLE t1;
-#DROP TABLE t2;
-#DROP TABLE t3;
+DROP TABLE t1;
+DROP TABLE t2;
+DROP TABLE t3;
-#sync_slave_with_master;
+sync_slave_with_master;
#we expect STOP SLAVE to produce a warning as the slave is stopped
#(the server was started with skip-slave-start)
-#--disable_warnings
-#stop slave;
-#--enable_warnings
-#--require r/slave-stopped.result
-#show status like 'Slave_running';
-#connection master;
-#reset master;
-#connection slave;
-#reset slave;
-#start slave;
-#--require r/slave-running.result
-#show status like 'Slave_running';
-#connection master;
+--disable_warnings
+stop slave;
+--enable_warnings
+--require r/slave-stopped.result
+show status like 'Slave_running';
+connection master;
+reset master;
+connection slave;
+reset slave;
+start slave;
+--require r/slave-running.result
+show status like 'Slave_running';
+connection master;
# We should be clean at this point, now we will run in the file from above.
-#--exec $MYSQL -e "source $MYSQLTEST_VARDIR/tmp/remote.sql"
+--exec $MYSQL -e "source $MYSQLTEST_VARDIR/tmp/remote.sql"
# Lets Check the tables on the Master
-#SELECT COUNT(*) from t1;
-#SELECT COUNT(*) from t2;
-#SELECT COUNT(*) from t3;
-#SELECT * FROM t1 ORDER BY word LIMIT 5;
-#SELECT * FROM t2 ORDER BY id LIMIT 5;
-#SELECT c1, c3, c4, c5 FROM t3 ORDER BY c1 LIMIT 5;
+SELECT COUNT(*) from t1;
+SELECT COUNT(*) from t2;
+SELECT COUNT(*) from t3;
+SELECT * FROM t1 ORDER BY word LIMIT 5;
+SELECT * FROM t2 ORDER BY id LIMIT 5;
+SELECT c1, c3, c4, c5 FROM t3 ORDER BY c1 LIMIT 5;
# Should have the same on the slave;
-#sync_slave_with_master;
-#SELECT COUNT(*) from t1;
-#SELECT COUNT(*) from t2;
-#SELECT COUNT(*) from t3;
-#SELECT * FROM t1 ORDER BY word LIMIT 5;
-#SELECT * FROM t2 ORDER BY id LIMIT 5;
-#SELECT c1, c3, c4, c5 FROM t3 ORDER BY c1 LIMIT 5;
-#connection master;
+sync_slave_with_master;
+SELECT COUNT(*) from t1;
+SELECT COUNT(*) from t2;
+SELECT COUNT(*) from t3;
+SELECT * FROM t1 ORDER BY word LIMIT 5;
+SELECT * FROM t2 ORDER BY id LIMIT 5;
+SELECT c1, c3, c4, c5 FROM t3 ORDER BY c1 LIMIT 5;
+connection master;
# We should be gold by the time, so I will get rid of our file.
-#--exec rm $MYSQLTEST_VARDIR/tmp/remote.sql
+--exec rm $MYSQLTEST_VARDIR/tmp/remote.sql
################### End Bug 17654 ######################
# LOAD DATA
@@ -315,7 +315,34 @@ select "--- Test cleanup --" as "";
--enable_query_log
# clean up
connection master;
-DROP TABLE IF EXISTS t1, t2, t3, t04, t05, t4, t5;
sync_slave_with_master;
+connection master;
+
+# BUG#17654 also test mysqlbinlog to ensure it can read the binlog from a remote server
+# and ensure that the results are the same as if read from a file (the same file).
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1 (a INT NOT NULL KEY, b INT);
+
+INSERT INTO t1 VALUES(1,1);
+
+SELECT * FROM t1;
+
+FLUSH LOGS;
+
+--exec $MYSQL_BINLOG --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000001 > $MYSQLTEST_VARDIR/tmp/remote.sql
+--exec $MYSQL_BINLOG $MYSQLTEST_VARDIR/log/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/local.sql
+
+--diff_files $MYSQLTEST_VARDIR/tmp/local.sql $MYSQLTEST_VARDIR/tmp/remote.sql
+
+--exec rm $MYSQLTEST_VARDIR/tmp/remote.sql
+
+--exec rm $MYSQLTEST_VARDIR/tmp/local.sql
+
+DROP TABLE IF EXISTS t1, t2, t3, t04, t05, t4, t5;
+
# End of 4.1 tests
diff --git a/mysql-test/t/xml.test b/mysql-test/t/xml.test
index 8517dce111f..1d16652ab1e 100644
--- a/mysql-test/t/xml.test
+++ b/mysql-test/t/xml.test
@@ -231,6 +231,13 @@ select UpdateXML(@xml, '/a/b/@bb1', 'bb3="bb3"');
select UpdateXML(@xml, '/a/b/@bb2', '');
select UpdateXML(@xml, '/a/b/@bb2', 'bb3="bb3"');
+#
+# Bug#27898 UPDATEXML Crashes the Server!
+#
+select updatexml('',
+ '/','1 | 2 |
') as upd1;
+select updatexml('', '/', '') as upd2;
+
#
# Bug#16234 XML: Crash if ExtractValue()
#
@@ -444,3 +451,85 @@ select ExtractValue('test', '/a/parent');
select ExtractValue('test', '/a/preceding');
select ExtractValue('test', '/a/preceding-sibling');
select ExtractValue('test', '/a/self');
+
+#
+# Bug#26518 XPath and variables problem
+# Check with user defined variables
+#
+set @i=1;
+select ExtractValue('b1b2','/a/b[$@i]');
+set @i=2;
+select ExtractValue('b1b2','/a/b[$@i]');
+set @i=NULL;
+select ExtractValue('b1b2','/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('b1b2b3');
+drop procedure spxml;
+
+#
+# Additional tests for bug#26518
+--echo Multiple matches, but no index specification
+SELECT ExtractValue('b1b2','/a/b');
+--echo No matches
+SELECT ExtractValue('b1b2','/a/c');
+--echo Index out of range
+SELECT ExtractValue('b1b2','/a/b[-1]');
+SELECT ExtractValue('b1b2','/a/b[10]');
+--echo With string-to-number conversion
+SELECT ExtractValue('b1b2','/a/b["1"]');
+SELECT ExtractValue('b1b2','/a/b["1 and string"]');
+SELECT ExtractValue('b1b2','/a/b["string and 1"]');
+SELECT ExtractValue('b1b2','/a/b["string"]');
+--echo String-to-number conversion from a user variable
+SET @i='1';
+SELECT ExtractValue('b1b2','/a/b[$@i]');
+SET @i='1 and string';
+SELECT ExtractValue('b1b2','/a/b[$@i]');
+SET @i='string and 1';
+SELECT ExtractValue('b1b2','/a/b[$@i]');
+SET @i='string';
+SELECT ExtractValue('b1b2','/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('b1b2', '1');
+CALL spxml('b1b2', '1 and string');
+CALL spxml('b1b2', 'string and 1');
+CALL spxml('b1b2', 'string');
+DROP PROCEDURE spxml;
+
+#
+# Bug#28558 UpdateXML called with garbage crashes server
+#
+--error 1105
+select UpdateXML('a',repeat('a b ',1000),'');
+--error 1105
+select ExtractValue('a', '/a[@x=@y0123456789_0123456789_0123456789_0123456789]');
+--error 1105
+select ExtractValue('a', '/a[@x=$y0123456789_0123456789_0123456789_0123456789]');
diff --git a/sql/item_xmlfunc.cc b/sql/item_xmlfunc.cc
index 26474990644..428bffa6879 100644
--- a/sql/item_xmlfunc.cc
+++ b/sql/item_xmlfunc.cc
@@ -19,7 +19,7 @@
#include "mysql_priv.h"
#include "my_xml.h"
-
+#include "sp_pcontext.h"
/*
TODO: future development directions:
@@ -923,8 +923,8 @@ static Item *create_comparator(MY_XPATH *xpath,
else if (a->type() == Item::XPATH_NODESET &&
b->type() == Item::XPATH_NODESET)
{
- uint len= context->end - context->beg;
- set_if_bigger(len, 32);
+ uint len= xpath->query.end - context->beg;
+ set_if_smaller(len, 32);
my_printf_error(ER_UNKNOWN_ERROR,
"XPATH error: "
"comparison of two nodesets is not supported: '%.*s'",
@@ -2412,21 +2412,78 @@ my_xpath_parse_QName(MY_XPATH *xpath)
}
-/*
+/**
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;
}
@@ -2534,12 +2591,10 @@ void Item_xml_str_func::fix_length_and_dec()
if (!rc)
{
- char context[32];
uint clen= xpath.query.end - xpath.lasttok.beg;
- set_if_bigger(clen, sizeof(context) - 1);
- strmake(context, xpath.lasttok.beg, clen);
- my_printf_error(ER_UNKNOWN_ERROR, "XPATH syntax error: '%s'",
- MYF(0), context);
+ set_if_smaller(clen, 32);
+ my_printf_error(ER_UNKNOWN_ERROR, "XPATH syntax error: '%.*s'",
+ MYF(0), clen, xpath.lasttok.beg);
return;
}
@@ -2768,6 +2823,16 @@ String *Item_func_xml_update::val_str(String *str)
nodebeg+= fltbeg->num;
+ if (!nodebeg->level)
+ {
+ /*
+ Root element, without NameTest:
+ UpdateXML(xml, '/', 'replacement');
+ Just return the replacement string.
+ */
+ return rep;
+ }
+
tmp_value.length(0);
tmp_value.set_charset(collation.collation);
uint offs= nodebeg->type == MY_XML_NODE_TAG ? 1 : 0;
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index a98797d7596..5c7a29df33b 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -413,9 +413,6 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
if (error)
{
- if (transactional_table)
- ha_autocommit_or_rollback(thd,error);
-
if (read_file_from_client)
while (!read_info.next_line())
;
@@ -463,6 +460,9 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
}
}
#endif /*!EMBEDDED_LIBRARY*/
+ if (transactional_table)
+ ha_autocommit_or_rollback(thd,error);
+
error= -1; // Error on read
goto err;
}
diff --git a/storage/heap/hp_hash.c b/storage/heap/hp_hash.c
index fbf3e541372..5ee0168d4b4 100644
--- a/storage/heap/hp_hash.c
+++ b/storage/heap/hp_hash.c
@@ -379,7 +379,13 @@ ulong hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
ulong hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
{
- register ulong nr=0;
+ /*
+ Note, if a key consists of a combination of numeric and
+ a text columns, it most likely won't work well.
+ Making text columns work with NEW_HASH_FUNCTION
+ needs also changes in strings/ctype-xxx.c.
+ */
+ ulong nr= 1, nr2= 4;
HA_KEYSEG *seg,*endseg;
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
@@ -401,14 +407,15 @@ ulong hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
}
if (seg->type == HA_KEYTYPE_TEXT)
{
- seg->charset->hash_sort(seg->charset,pos,((uchar*)key)-pos,&nr,NULL);
+ seg->charset->coll->hash_sort(seg->charset, pos, ((uchar*)key)-pos,
+ &nr, &nr2);
}
else if (seg->type == HA_KEYTYPE_VARTEXT1) /* Any VARCHAR segments */
{
uint pack_length= 2; /* Key packing is constant */
uint length= uint2korr(pos);
- seg->charset->hash_sort(seg->charset, pos+pack_length, length, &nr,
- NULL);
+ seg->charset->coll->hash_sort(seg->charset, pos+pack_length, length,
+ &nr, &nr2);
key+= pack_length;
}
else
@@ -428,7 +435,7 @@ ulong hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
ulong hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
{
- register ulong nr=0;
+ ulong nr= 1, nr2= 4;
HA_KEYSEG *seg,*endseg;
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
@@ -444,14 +451,16 @@ ulong hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
}
if (seg->type == HA_KEYTYPE_TEXT)
{
- seg->charset->hash_sort(seg->charset,pos,((uchar*)key)-pos,&nr,NULL);
+ uint char_length= seg->length; /* TODO: fix to use my_charpos() */
+ seg->charset->coll->hash_sort(seg->charset, pos, char_length,
+ &nr, &nr2);
}
else if (seg->type == HA_KEYTYPE_VARTEXT1) /* Any VARCHAR segments */
{
uint pack_length= seg->bit_start;
uint length= (pack_length == 1 ? (uint) *(uchar*) pos : uint2korr(pos));
- seg->charset->hash_sort(seg->charset, pos+pack_length,
- length, &nr, NULL);
+ seg->charset->coll->hash_sort(seg->charset, pos+pack_length,
+ length, &nr, &nr2);
}
else
{