Bug#25714

  "getGeneratedKeys() does not work with FEDERATED table"
  mysql_insert() expected the storage engine to update the row data
  during the write_row() operation with the value of the new auto-
  increment field. The field must be updated when only one row has
  been inserted as mysql_insert() would ignore the thd->last_insert.
  This patch implements HA_STATUS_AUTO support in ha_federated::info()
  and ensures that ha_federated::write_row() does update the row's
  auto-increment value.
  The test case was written in C as the protocol's 'id' value is
  accessible through libmysqlclient and not via SQL statements.
  mysql-test-run.pl was extended to enable running the test binary.
parent c04ae188
#
# Check if the variable MYSQL_BUG25714 is set
#
--require r/have_bug25714.require
disable_query_log;
eval select LENGTH("MYSQL_BUG25714") > 0 as "have_bug25714_exe";
enable_query_log;
...@@ -144,6 +144,7 @@ our $exe_mysqladmin; ...@@ -144,6 +144,7 @@ our $exe_mysqladmin;
our $exe_mysql_upgrade; our $exe_mysql_upgrade;
our $exe_mysqlbinlog; our $exe_mysqlbinlog;
our $exe_mysql_client_test; our $exe_mysql_client_test;
our $exe_bug25714;
our $exe_mysqld; our $exe_mysqld;
our $exe_mysqlcheck; our $exe_mysqlcheck;
our $exe_mysqldump; our $exe_mysqldump;
...@@ -1630,6 +1631,12 @@ sub executable_setup () { ...@@ -1630,6 +1631,12 @@ sub executable_setup () {
"$glob_basedir/tests/mysql_client_test", "$glob_basedir/tests/mysql_client_test",
"$glob_basedir/bin/mysql_client_test"); "$glob_basedir/bin/mysql_client_test");
} }
# Look for bug25714 executable which may _not_ exist in
# some versions, test using it should be skipped
$exe_bug25714=
mtr_exe_maybe_exists(vs_config_dirs('tests', 'bug25714'),
"$glob_basedir/tests/bug25714");
} }
...@@ -2010,6 +2017,11 @@ sub environment_setup () { ...@@ -2010,6 +2017,11 @@ sub environment_setup () {
$ENV{'MYSQL'}= $cmdline_mysql; $ENV{'MYSQL'}= $cmdline_mysql;
# ----------------------------------------------------
# Setup env so childs can execute bug25714
# ----------------------------------------------------
$ENV{'MYSQL_BUG25714'}= $exe_bug25714;
# ---------------------------------------------------- # ----------------------------------------------------
# Setup env so childs can execute mysql_client_test # Setup env so childs can execute mysql_client_test
# ---------------------------------------------------- # ----------------------------------------------------
......
stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
stop slave;
DROP DATABASE IF EXISTS federated;
CREATE DATABASE federated;
DROP DATABASE IF EXISTS federated;
CREATE DATABASE federated;
DROP TABLE IF EXISTS federated.bug_13118_table;
CREATE TABLE federated.t1 (
`id` int auto_increment primary key,
`value` int
) ENGINE=MyISAM;
INSERT INTO federated.t1 SET value=1;
INSERT INTO federated.t1 SET value=2;
INSERT INTO federated.t1 SET value=2;
DROP TABLE IF EXISTS federated.t1;
CREATE TABLE federated.t1 (
`id` int auto_increment primary key,
`value` int
) ENGINE=FEDERATED
CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1';
SELECT * from federated.t1;
id value
1 1
2 2
3 2
INSERT INTO federated.t1 SET value=4;
SELECT LAST_INSERT_ID();
LAST_INSERT_ID()
4
5 inserted
6 inserted
7 inserted
8 inserted
SELECT * from federated.t1;
id value
1 1
2 2
3 2
4 4
5 54
6 55
7 54
8 55
DROP TABLE federated.t1;
DROP TABLE federated.t1;
DROP TABLE IF EXISTS federated.t1;
DROP DATABASE IF EXISTS federated;
DROP TABLE IF EXISTS federated.t1;
DROP DATABASE IF EXISTS federated;
--source include/have_bug25714.inc
source include/federated.inc;
connection slave;
--disable_warnings
DROP TABLE IF EXISTS federated.bug_13118_table;
--enable_warnings
CREATE TABLE federated.t1 (
`id` int auto_increment primary key,
`value` int
) ENGINE=MyISAM;
INSERT INTO federated.t1 SET value=1;
INSERT INTO federated.t1 SET value=2;
INSERT INTO federated.t1 SET value=2;
connection master;
--disable_warnings
DROP TABLE IF EXISTS federated.t1;
--enable_warnings
--replace_result $SLAVE_MYPORT SLAVE_PORT
eval CREATE TABLE federated.t1 (
`id` int auto_increment primary key,
`value` int
) ENGINE=FEDERATED
CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1';
SELECT * from federated.t1;
INSERT INTO federated.t1 SET value=4;
SELECT LAST_INSERT_ID();
--exec $MYSQL_BUG25714 $SLAVE_MYPORT
--exec $MYSQL_BUG25714 $MASTER_MYPORT
SELECT * from federated.t1;
DROP TABLE federated.t1;
connection slave;
DROP TABLE federated.t1;
source include/federated_cleanup.inc;
...@@ -1811,8 +1811,13 @@ int ha_federated::write_row(byte *buf) ...@@ -1811,8 +1811,13 @@ int ha_federated::write_row(byte *buf)
field, then store the last_insert_id() value from the foreign server field, then store the last_insert_id() value from the foreign server
*/ */
if (auto_increment_update_required) if (auto_increment_update_required)
{
update_auto_increment(); update_auto_increment();
/* mysql_insert() uses this for protocol return value */
table->next_number_field->store(auto_increment_value, 1);
}
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -1896,7 +1901,8 @@ void ha_federated::update_auto_increment(void) ...@@ -1896,7 +1901,8 @@ void ha_federated::update_auto_increment(void)
THD *thd= current_thd; THD *thd= current_thd;
DBUG_ENTER("ha_federated::update_auto_increment"); DBUG_ENTER("ha_federated::update_auto_increment");
thd->insert_id(mysql->last_used_con->insert_id); ha_federated::info(HA_STATUS_AUTO);
thd->insert_id(auto_increment_value);
DBUG_PRINT("info",("last_insert_id: %ld", (long) auto_increment_value)); DBUG_PRINT("info",("last_insert_id: %ld", (long) auto_increment_value));
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
...@@ -2688,8 +2694,10 @@ int ha_federated::info(uint flag) ...@@ -2688,8 +2694,10 @@ int ha_federated::info(uint flag)
block_size= 4096; block_size= 4096;
} }
if (result) if (flag & HA_STATUS_AUTO)
mysql_free_result(result); auto_increment_value= mysql->last_used_con->insert_id;
mysql_free_result(result);
DBUG_RETURN(0); DBUG_RETURN(0);
......
...@@ -28,7 +28,7 @@ EXTRA_DIST = auto_increment.res auto_increment.tst \ ...@@ -28,7 +28,7 @@ EXTRA_DIST = auto_increment.res auto_increment.tst \
CMakeLists.txt CMakeLists.txt
bin_PROGRAMS = mysql_client_test bin_PROGRAMS = mysql_client_test
noinst_PROGRAMS = insert_test select_test thread_test noinst_PROGRAMS = insert_test select_test thread_test bug25714
INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include \ INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include \
$(openssl_includes) $(openssl_includes)
...@@ -45,6 +45,9 @@ select_test_SOURCES= select_test.c ...@@ -45,6 +45,9 @@ select_test_SOURCES= select_test.c
insert_test_DEPENDENCIES= $(LIBRARIES) $(pkglib_LTLIBRARIES) insert_test_DEPENDENCIES= $(LIBRARIES) $(pkglib_LTLIBRARIES)
select_test_DEPENDENCIES= $(LIBRARIES) $(pkglib_LTLIBRARIES) select_test_DEPENDENCIES= $(LIBRARIES) $(pkglib_LTLIBRARIES)
bug25714_SOURCES= bug25714.c
bug25714_DEPENDENCIES= $(LIBRARIES) $(pkglib_LTLIBRARIES)
# Fix for mit-threads # Fix for mit-threads
DEFS = -DUNDEF_THREADS_HACK DEFS = -DUNDEF_THREADS_HACK
......
/* Copyright (C) 2007 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <mysql.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
int main (int argc, char **argv)
{
MYSQL conn;
int OK;
const char* query4= "INSERT INTO federated.t1 SET Value=54";
const char* query5= "INSERT INTO federated.t1 SET Value=55";
if (argc != 2)
return -1;
mysql_init(&conn);
if (!mysql_real_connect(
&conn,
"127.0.0.1",
"root",
"",
"test",
atoi(argv[1]),
NULL,
CLIENT_FOUND_ROWS))
{
fprintf(stderr, "Failed to connect to database: Error: %s\n",
mysql_error(&conn));
return 1;
} else {
printf("%s\n", mysql_error(&conn));
}
OK = mysql_real_query (&conn, query4, strlen(query4));
assert(0 == OK);
printf("%ld inserted\n",
(long) mysql_insert_id(&conn));
OK = mysql_real_query (&conn, query5, strlen(query5));
assert(0 == OK);
printf("%ld inserted\n",
(long) mysql_insert_id(&conn));
mysql_close(&conn);
return 0;
};
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment