Merge jamppa@bk-internal.mysql.com:/home/bk/mysql-5.1-new

into  a193-229-222-105.elisa-laajakaista.fi:/home/my/bk/mysql-5.1-new


configure.in:
  Auto merged
sql/mysqld.cc:
  Auto merged
sql/set_var.cc:
  Auto merged
This commit is contained in:
unknown 2006-02-05 11:06:29 +02:00
commit fd03e915ea
108 changed files with 1280 additions and 431 deletions

View File

@ -48,6 +48,7 @@
50 50
=6 =6
BUILD/compile-pentium-maintainer BUILD/compile-pentium-maintainer
BitKeeper/etc/RESYNC_TREE
BitKeeper/etc/config BitKeeper/etc/config
BitKeeper/etc/csets BitKeeper/etc/csets
BitKeeper/etc/csets-in BitKeeper/etc/csets-in
@ -295,6 +296,7 @@ libmysql/*.ds?
libmysql/*.vcproj libmysql/*.vcproj
libmysql/conf_to_src libmysql/conf_to_src
libmysql/debug/libmysql.exp libmysql/debug/libmysql.exp
libmysql/libmysql.ver
libmysql/my_static.h libmysql/my_static.h
libmysql/my_time.c libmysql/my_time.c
libmysql/mysys_priv.h libmysql/mysys_priv.h
@ -1611,4 +1613,3 @@ vio/viotest-sslconnect.cpp
vio/viotest.cpp vio/viotest.cpp
zlib/*.ds? zlib/*.ds?
zlib/*.vcproj zlib/*.vcproj
BitKeeper/etc/RESYNC_TREE

View File

@ -45,22 +45,22 @@ CLEAN_FILES: $(TXT_FILES)
GT = $(srcdir)/Support/generate-text-files.pl GT = $(srcdir)/Support/generate-text-files.pl
../INSTALL-SOURCE: mysql.info $(GT) ../INSTALL-SOURCE: mysql.info $(GT)
perl -w $(GT) $< "installing-source" "windows-source-build" > $@ perl -w $(GT) mysql.info "installing-source" "windows-source-build" > $@
../INSTALL-WIN-SOURCE: mysql.info $(GT) ../INSTALL-WIN-SOURCE: mysql.info $(GT)
perl -w $(GT) $< "windows-source-build" "post-installation" > $@ perl -w $(GT) mysql.info "windows-source-build" "post-installation" > $@
# We put the description for the binary installation here so that # We put the description for the binary installation here so that
# people who download source wont have to see it. It is moved up to # people who download source wont have to see it. It is moved up to
# the toplevel by the script that makes the binary tar files. # the toplevel by the script that makes the binary tar files.
INSTALL-BINARY: mysql.info $(GT) INSTALL-BINARY: mysql.info $(GT)
perl -w $(GT) $< "installing-binary" "installing-source" > $@ perl -w $(GT) mysql.info "installing-binary" "installing-source" > $@
../EXCEPTIONS-CLIENT: mysql.info $(GT) ../EXCEPTIONS-CLIENT: mysql.info $(GT)
perl -w $(GT) $< "mysql-floss-license-exception" "function-index" > $@ perl -w $(GT) mysql.info "mysql-floss-license-exception" "function-index" > $@
../support-files/MacOSX/ReadMe.txt: mysql.info $(GT) ../support-files/MacOSX/ReadMe.txt: mysql.info $(GT)
perl -w $(GT) $< "mac-os-x-installation" "netware-installation" > $@ perl -w $(GT) mysql.info "mac-os-x-installation" "netware-installation" > $@
# Don't update the files from bitkeeper # Don't update the files from bitkeeper
%::SCCS/s.% %::SCCS/s.%

View File

@ -569,6 +569,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
return -1; return -1;
} }
mysql_close(mysql); /* Close connection to avoid error messages */ mysql_close(mysql); /* Close connection to avoid error messages */
argc=1; /* force SHUTDOWN to be the last command */
if (got_pidfile) if (got_pidfile)
{ {
if (opt_verbose) if (opt_verbose)

View File

@ -1293,12 +1293,13 @@ at offset %lu ; this could be a log format error or read error",
} }
else if (buf[4] == ROTATE_EVENT) else if (buf[4] == ROTATE_EVENT)
{ {
Log_event *ev;
my_b_seek(file, tmp_pos); /* seek back to event's start */ my_b_seek(file, tmp_pos); /* seek back to event's start */
if (!Log_event::read_log_event(file, *description_event)) if (!(ev= Log_event::read_log_event(file, *description_event)))
/* EOF can't be hit here normally, so it's a real error */ /* EOF can't be hit here normally, so it's a real error */
die("Could not read a Rotate_log_event event \ die("Could not read a Rotate_log_event event at offset %lu ;"
at offset %lu ; this could be a log format error or read error", " this could be a log format error or read error", tmp_pos);
tmp_pos); delete ev;
} }
else else
break; break;

View File

@ -1316,7 +1316,7 @@ static uint dump_routines_for_db(char *db)
fprintf(sql_file, "DELIMITER ;\n"); fprintf(sql_file, "DELIMITER ;\n");
if (lock_tables) if (lock_tables)
mysql_query_with_error_report(sock, 0, "UNLOCK TABLES"); VOID(mysql_query_with_error_report(sock, 0, "UNLOCK TABLES"));
DBUG_RETURN(0); DBUG_RETURN(0);
} }
@ -2139,7 +2139,10 @@ static void dump_table(char *table, char *db)
else else
res=mysql_store_result(sock); res=mysql_store_result(sock);
if (!res) if (!res)
{
DB_error(sock, "when retrieving data from server"); DB_error(sock, "when retrieving data from server");
goto err;
}
if (verbose) if (verbose)
fprintf(stderr, "-- Retrieving rows...\n"); fprintf(stderr, "-- Retrieving rows...\n");
if (mysql_num_fields(res) != num_fields) if (mysql_num_fields(res) != num_fields)
@ -2794,7 +2797,7 @@ static int dump_all_tables_in_db(char *database)
check_io(md_result_file); check_io(md_result_file);
} }
if (lock_tables) if (lock_tables)
mysql_query_with_error_report(sock, 0, "UNLOCK TABLES"); VOID(mysql_query_with_error_report(sock, 0, "UNLOCK TABLES"));
return 0; return 0;
} /* dump_all_tables_in_db */ } /* dump_all_tables_in_db */
@ -2849,23 +2852,23 @@ static my_bool dump_all_views_in_db(char *database)
check_io(md_result_file); check_io(md_result_file);
} }
if (lock_tables) if (lock_tables)
mysql_query(sock,"UNLOCK TABLES"); VOID(mysql_query_with_error_report(sock, 0, "UNLOCK TABLES"));
return 0; return 0;
} /* dump_all_tables_in_db */ } /* dump_all_tables_in_db */
/* /*
get_actual_table_name -- executes a SHOW TABLES LIKE '%s' to get the actual get_actual_table_name -- executes a SHOW TABLES LIKE '%s' to get the actual
table name from the server for the table name given on the command line. table name from the server for the table name given on the command line.
we do this because the table name given on the command line may be a we do this because the table name given on the command line may be a
different case (e.g. T1 vs t1) different case (e.g. T1 vs t1)
RETURN RETURN
int - 0 if a tablename was retrieved. 1 if not int - 0 if a tablename was retrieved. 1 if not
*/ */
static int get_actual_table_name(const char *old_table_name, static int get_actual_table_name(const char *old_table_name,
char *new_table_name, char *new_table_name,
int buf_size) int buf_size)
{ {
int retval; int retval;
@ -2877,7 +2880,7 @@ static int get_actual_table_name(const char *old_table_name,
/* Check memory for quote_for_like() */ /* Check memory for quote_for_like() */
DBUG_ASSERT(2*sizeof(old_table_name) < sizeof(show_name_buff)); DBUG_ASSERT(2*sizeof(old_table_name) < sizeof(show_name_buff));
my_snprintf(query, sizeof(query), "SHOW TABLES LIKE %s", my_snprintf(query, sizeof(query), "SHOW TABLES LIKE %s",
quote_for_like(old_table_name, show_name_buff)); quote_for_like(old_table_name, show_name_buff));
if (mysql_query_with_error_report(sock, 0, query)) if (mysql_query_with_error_report(sock, 0, query))
@ -2886,7 +2889,7 @@ static int get_actual_table_name(const char *old_table_name,
} }
retval = 1; retval = 1;
if ((table_res= mysql_store_result(sock))) if ((table_res= mysql_store_result(sock)))
{ {
my_ulonglong num_rows= mysql_num_rows(table_res); my_ulonglong num_rows= mysql_num_rows(table_res);
@ -3008,7 +3011,7 @@ static int dump_selected_tables(char *db, char **table_names, int tables)
check_io(md_result_file); check_io(md_result_file);
} }
if (lock_tables) if (lock_tables)
mysql_query_with_error_report(sock, 0, "UNLOCK TABLES"); VOID(mysql_query_with_error_report(sock, 0, "UNLOCK TABLES"));
DBUG_RETURN(0); DBUG_RETURN(0);
} /* dump_selected_tables */ } /* dump_selected_tables */

View File

@ -676,8 +676,8 @@ history_load(History *h, const char *fname)
(void) strunvis(ptr, line); (void) strunvis(ptr, line);
line[sz] = c; line[sz] = c;
if (HENTER(h, &ev, ptr) == -1) { if (HENTER(h, &ev, ptr) == -1) {
h_free((ptr_t)ptr); i = -1;
return -1; goto oomem;
} }
} }
oomem: oomem:

View File

@ -13,7 +13,8 @@ AM_CONFIG_HEADER(config.h)
PROTOCOL_VERSION=10 PROTOCOL_VERSION=10
DOT_FRM_VERSION=6 DOT_FRM_VERSION=6
# See the libtool docs for information on how to do shared lib versions. # See the libtool docs for information on how to do shared lib versions.
SHARED_LIB_VERSION=15:0:0 SHARED_LIB_MAJOR_VERSION=15
SHARED_LIB_VERSION=$SHARED_LIB_MAJOR_VERSION:0:0
# Set all version vars based on $VERSION. How do we do this more elegant ? # Set all version vars based on $VERSION. How do we do this more elegant ?
# Remember that regexps needs to quote [ and ] since this is run through m4 # Remember that regexps needs to quote [ and ] since this is run through m4
@ -60,6 +61,7 @@ AC_DEFINE_UNQUOTED([PROTOCOL_VERSION], [$PROTOCOL_VERSION],
AC_SUBST(DOT_FRM_VERSION) AC_SUBST(DOT_FRM_VERSION)
AC_DEFINE_UNQUOTED([DOT_FRM_VERSION], [$DOT_FRM_VERSION], AC_DEFINE_UNQUOTED([DOT_FRM_VERSION], [$DOT_FRM_VERSION],
[Version of .frm files]) [Version of .frm files])
AC_SUBST(SHARED_LIB_MAJOR_VERSION)
AC_SUBST(SHARED_LIB_VERSION) AC_SUBST(SHARED_LIB_VERSION)
AC_SUBST(AVAILABLE_LANGUAGES) AC_SUBST(AVAILABLE_LANGUAGES)
@ -339,6 +341,13 @@ fi
MYSQL_PROG_AR MYSQL_PROG_AR
# libmysqlclient versioning when linked with GNU ld.
if $LD --version 2>/dev/null|grep -q GNU; then
LD_VERSION_SCRIPT="-Wl,--version-script=\$(top_srcdir)/libmysql/libmysql.ver"
AC_CONFIG_FILES(libmysql/libmysql.ver)
fi
AC_SUBST(LD_VERSION_SCRIPT)
# Avoid bug in fcntl on some versions of linux # Avoid bug in fcntl on some versions of linux
AC_MSG_CHECKING("if we should use 'skip-locking' as default for $target_os") AC_MSG_CHECKING("if we should use 'skip-locking' as default for $target_os")
# Any variation of Linux # Any variation of Linux

View File

@ -426,7 +426,8 @@ enum ha_base_keytype {
enum en_fieldtype { enum en_fieldtype {
FIELD_LAST=-1,FIELD_NORMAL,FIELD_SKIP_ENDSPACE,FIELD_SKIP_PRESPACE, FIELD_LAST=-1,FIELD_NORMAL,FIELD_SKIP_ENDSPACE,FIELD_SKIP_PRESPACE,
FIELD_SKIP_ZERO,FIELD_BLOB,FIELD_CONSTANT,FIELD_INTERVALL,FIELD_ZERO, FIELD_SKIP_ZERO,FIELD_BLOB,FIELD_CONSTANT,FIELD_INTERVALL,FIELD_ZERO,
FIELD_VARCHAR,FIELD_CHECK FIELD_VARCHAR,FIELD_CHECK,
FIELD_enum_val_count
}; };
enum data_file_type { enum data_file_type {

View File

@ -77,7 +77,7 @@ mysysobjects2 = my_lib.lo
mysysobjects = $(mysysobjects1) $(mysysobjects2) mysysobjects = $(mysysobjects1) $(mysysobjects2)
target_libadd = $(mysysobjects) $(mystringsobjects) $(dbugobjects) \ target_libadd = $(mysysobjects) $(mystringsobjects) $(dbugobjects) \
$(sql_cmn_objects) $(vio_objects) $(sqlobjects) $(sql_cmn_objects) $(vio_objects) $(sqlobjects)
target_ldflags = -version-info @SHARED_LIB_VERSION@ target_ldflags = -version-info @SHARED_LIB_VERSION@ @LD_VERSION_SCRIPT@
vio_objects= vio.lo viosocket.lo viossl.lo viosslfactories.lo vio_objects= vio.lo viosocket.lo viossl.lo viosslfactories.lo
CLEANFILES = $(target_libadd) $(SHLIBOBJS) \ CLEANFILES = $(target_libadd) $(SHLIBOBJS) \
$(target) $(target)

View File

@ -818,7 +818,7 @@ my_bool handle_local_infile(MYSQL *mysql, const char *net_filename)
if ((*options->local_infile_init)(&li_ptr, net_filename, if ((*options->local_infile_init)(&li_ptr, net_filename,
options->local_infile_userdata)) options->local_infile_userdata))
{ {
my_net_write(net,"",0); /* Server needs one packet */ VOID(my_net_write(net,"",0)); /* Server needs one packet */
net_flush(net); net_flush(net);
strmov(net->sqlstate, unknown_sqlstate); strmov(net->sqlstate, unknown_sqlstate);
net->last_errno= (*options->local_infile_error)(li_ptr, net->last_errno= (*options->local_infile_error)(li_ptr,
@ -2817,7 +2817,7 @@ my_bool STDCALL mysql_stmt_attr_get(MYSQL_STMT *stmt,
{ {
switch (attr_type) { switch (attr_type) {
case STMT_ATTR_UPDATE_MAX_LENGTH: case STMT_ATTR_UPDATE_MAX_LENGTH:
*(ulong*) value= stmt->update_max_length; *(my_bool*) value= stmt->update_max_length;
break; break;
case STMT_ATTR_CURSOR_TYPE: case STMT_ATTR_CURSOR_TYPE:
*(ulong*) value= stmt->flags; *(ulong*) value= stmt->flags;

1
libmysql/libmysql.ver.in Normal file
View File

@ -0,0 +1 @@
libmysqlclient_@SHARED_LIB_MAJOR_VERSION@ { global: *; };

View File

@ -234,5 +234,10 @@ insert into t1 values('test test '),('test'),('test'),('test'),
('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'), ('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'),
('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'); ('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test');
delete from t1 limit 1; delete from t1 limit 1;
truncate table t1;
insert into t1 values('ab c d');
update t1 set a='ab c d';
select * from t1 where match a against('ab c' in boolean mode);
a
drop table t1; drop table t1;
set names latin1; set names latin1;

View File

@ -1126,6 +1126,19 @@ DROP TABLE t1;
DROP VIEW v1; DROP VIEW v1;
DROP FUNCTION func1; DROP FUNCTION func1;
DROP FUNCTION func2; DROP FUNCTION func2;
create database mysqltest;
create table mysqltest.t1(a int);
select table_schema from information_schema.tables where table_schema='mysqltest';
table_schema
drop database mysqltest;
select column_type, group_concat(table_schema, '.', table_name), count(*) as num
from information_schema.columns where
table_schema='information_schema' and
(column_type = 'varchar(7)' or column_type = 'varchar(20)')
group by column_type order by num;
column_type group_concat(table_schema, '.', table_name) num
varchar(7) information_schema.ROUTINES,information_schema.VIEWS 2
varchar(20) information_schema.COLUMNS,information_schema.FILES,information_schema.FILES,information_schema.PLUGINS,information_schema.PLUGINS,information_schema.PLUGINS 6
select * from information_schema.engines WHERE ENGINE="MyISAM"; select * from information_schema.engines WHERE ENGINE="MyISAM";
ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS
MyISAM ENABLED Default engine as of MySQL 3.23 with great performance NO NO NO MyISAM ENABLED Default engine as of MySQL 3.23 with great performance NO NO NO

View File

@ -0,0 +1,25 @@
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;
drop database if exists d1;
drop database if exists d2;
drop database if exists d2;
create database d1;
create table d1.t0 (id int);
create database d2;
use d2;
create table t1 (id int);
create table t2 (id int);
insert into t1 values (1), (2), (3), (4), (5);
insert into t2 select id + 3 from t1;
update t1 join t2 using (id) set t1.id = 0;
insert into d1.t0 values (0);
use d1;
select * from t0 where id=0;
id
0
drop database d1;
drop database d2;

View File

@ -401,5 +401,18 @@ drop function f1;
select * from t1; select * from t1;
a a
1 1
DROP PROCEDURE IF EXISTS p1;
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(col VARCHAR(10));
CREATE PROCEDURE p1(arg VARCHAR(10))
INSERT INTO t1 VALUES(arg);
CALL p1('test');
SELECT * FROM t1;
col
test
SELECT * FROM t1;
col
test
DROP PROCEDURE p1;
drop table t1; drop table t1;
reset master; reset master;

View File

@ -1115,3 +1115,22 @@ ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function
drop function bug11555_1; drop function bug11555_1;
drop table t1; drop table t1;
drop view v1; drop view v1;
drop procedure if exists ` bug15658`;
create procedure ``() select 1;
ERROR 42000: Incorrect routine name ''
create procedure ` `() select 1;
ERROR 42000: Incorrect routine name ' '
create procedure `bug15658 `() select 1;
ERROR 42000: Incorrect routine name 'bug15658 '
create procedure ``.bug15658() select 1;
ERROR 42000: Incorrect database name ''
create procedure `x `.bug15658() select 1;
ERROR 42000: Incorrect database name 'x '
create procedure ` bug15658`() select 1;
call ` bug15658`();
1
1
show procedure status;
Db Name Type Definer Modified Created Security_type Comment
test bug15658 PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
drop procedure ` bug15658`;

View File

@ -263,3 +263,24 @@ CREATE VIEW v1 AS SELECT test.bug12812()|
ERROR 42000: execute command denied to user 'user_bug12812'@'localhost' for routine 'test.bug12812' ERROR 42000: execute command denied to user 'user_bug12812'@'localhost' for routine 'test.bug12812'
DROP USER user_bug12812@localhost| DROP USER user_bug12812@localhost|
drop function bug12812| drop function bug12812|
create database db_bug14834;
create user user1_bug14834@localhost identified by '';
grant all on `db\_bug14834`.* to user1_bug14834@localhost;
create user user2_bug14834@localhost identified by '';
grant all on `db\_bug14834`.* to user2_bug14834@localhost;
create user user3_bug14834@localhost identified by '';
grant all on `db__ug14834`.* to user3_bug14834@localhost;
create procedure p_bug14834() select user(), current_user();
call p_bug14834();
user() current_user()
user1_bug14834@localhost user1_bug14834@localhost
call p_bug14834();
user() current_user()
user2_bug14834@localhost user1_bug14834@localhost
call p_bug14834();
user() current_user()
user3_bug14834@localhost user1_bug14834@localhost
drop user user1_bug14834@localhost;
drop user user2_bug14834@localhost;
drop user user3_bug14834@localhost;
drop database db_bug14834;

View File

@ -1178,8 +1178,8 @@ drop view v2|
delete from t1 | delete from t1 |
delete from t2 | delete from t2 |
drop table t4| drop table t4|
drop table if exists fac| drop table if exists t3|
create table fac (n int unsigned not null primary key, f bigint unsigned)| create table t3 (n int unsigned not null primary key, f bigint unsigned)|
drop procedure if exists ifac| drop procedure if exists ifac|
create procedure ifac(n int unsigned) create procedure ifac(n int unsigned)
begin begin
@ -1189,13 +1189,13 @@ set n = 20; # bigint overflow otherwise
end if; end if;
while i <= n do while i <= n do
begin begin
insert into test.fac values (i, fac(i)); insert into test.t3 values (i, fac(i));
set i = i + 1; set i = i + 1;
end; end;
end while; end while;
end| end|
call ifac(20)| call ifac(20)|
select * from fac| select * from t3|
n f n f
1 1 1 1
2 2 2 2
@ -1217,7 +1217,7 @@ n f
18 6402373705728000 18 6402373705728000
19 121645100408832000 19 121645100408832000
20 2432902008176640000 20 2432902008176640000
drop table fac| drop table t3|
show function status like '%f%'| show function status like '%f%'|
Db Name Type Definer Modified Created Security_type Comment Db Name Type Definer Modified Created Security_type Comment
test fac FUNCTION root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER test fac FUNCTION root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
@ -1225,12 +1225,12 @@ drop procedure ifac|
drop function fac| drop function fac|
show function status like '%f%'| show function status like '%f%'|
Db Name Type Definer Modified Created Security_type Comment Db Name Type Definer Modified Created Security_type Comment
drop table if exists primes| drop table if exists t3|
create table primes ( create table t3 (
i int unsigned not null primary key, i int unsigned not null primary key,
p bigint unsigned not null p bigint unsigned not null
)| )|
insert into primes values insert into t3 values
( 0, 3), ( 1, 5), ( 2, 7), ( 3, 11), ( 4, 13), ( 0, 3), ( 1, 5), ( 2, 7), ( 3, 11), ( 4, 13),
( 5, 17), ( 6, 19), ( 7, 23), ( 8, 29), ( 9, 31), ( 5, 17), ( 6, 19), ( 7, 23), ( 8, 29), ( 9, 31),
(10, 37), (11, 41), (12, 43), (13, 47), (14, 53), (10, 37), (11, 41), (12, 43), (13, 47), (14, 53),
@ -1253,7 +1253,7 @@ set b = b+200, s = 0;
else else
begin begin
declare p bigint unsigned; declare p bigint unsigned;
select t.p into p from test.primes t where t.i = s; select t.p into p from test.t3 t where t.i = s;
if b+p > r then if b+p > r then
set pp = 1; set pp = 1;
leave again; leave again;
@ -1278,7 +1278,7 @@ begin
declare pp bool default 0; declare pp bool default 0;
call opp(p, pp); call opp(p, pp);
if pp then if pp then
insert into test.primes values (i, p); insert into test.t3 values (i, p);
set i = i+1; set i = i+1;
end if; end if;
set p = p+2; set p = p+2;
@ -1299,7 +1299,7 @@ set b = b+200, s = 0;
else else
begin begin
declare p bigint unsigned; declare p bigint unsigned;
select t.p into p from test.primes t where t.i = s; select t.p into p from test.t3 t where t.i = s;
if b+p > r then if b+p > r then
set pp = 1; set pp = 1;
leave again; leave again;
@ -1318,47 +1318,47 @@ Db Name Type Definer Modified Created Security_type Comment
test ip PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER test ip PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
test opp PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER test opp PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
call ip(200)| call ip(200)|
select * from primes where i=45 or i=100 or i=199| select * from t3 where i=45 or i=100 or i=199|
i p i p
45 211 45 211
100 557 100 557
199 1229 199 1229
drop table primes| drop table t3|
drop procedure opp| drop procedure opp|
drop procedure ip| drop procedure ip|
show procedure status like '%p%'| show procedure status like '%p%'|
Db Name Type Definer Modified Created Security_type Comment Db Name Type Definer Modified Created Security_type Comment
drop table if exists fib| drop table if exists t3|
create table fib ( f bigint unsigned not null )| create table t3 ( f bigint unsigned not null )|
drop procedure if exists fib| drop procedure if exists fib|
create procedure fib(n int unsigned) create procedure fib(n int unsigned)
begin begin
if n > 1 then if n > 1 then
begin begin
declare x, y bigint unsigned; declare x, y bigint unsigned;
declare c cursor for select f from fib order by f desc limit 2; declare c cursor for select f from t3 order by f desc limit 2;
open c; open c;
fetch c into y; fetch c into y;
fetch c into x; fetch c into x;
close c; close c;
insert into fib values (x+y); insert into t3 values (x+y);
call fib(n-1); call fib(n-1);
end; end;
end if; end if;
end| end|
set @@max_sp_recursion_depth= 20| set @@max_sp_recursion_depth= 20|
insert into fib values (0), (1)| insert into t3 values (0), (1)|
call fib(3)| call fib(3)|
select * from fib order by f asc| select * from t3 order by f asc|
f f
0 0
1 1
1 1
2 2
delete from fib| delete from t3|
insert into fib values (0), (1)| insert into t3 values (0), (1)|
call fib(20)| call fib(10)|
select * from fib order by f asc| select * from t3 order by f asc|
f f
0 0
1 1
@ -1371,17 +1371,7 @@ f
21 21
34 34
55 55
89 drop table t3|
144
233
377
610
987
1597
2584
4181
6765
drop table fib|
drop procedure fib| drop procedure fib|
set @@max_sp_recursion_depth= 0| set @@max_sp_recursion_depth= 0|
drop procedure if exists bar| drop procedure if exists bar|

View File

@ -1,4 +1,4 @@
drop table if exists t1, t2; drop table if exists t1, t2, t3;
drop procedure if exists bug8850| drop procedure if exists bug8850|
create table t1 (a int) engine=innodb| create table t1 (a int) engine=innodb|
create procedure bug8850() create procedure bug8850()

View File

@ -215,9 +215,9 @@ select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from
a a
select b,(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2) from t4; select b,(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2) from t4;
b (select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2) b (select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2)
8 7.5000 8 7.5
8 4.5000 8 4.5
9 7.5000 9 7.5
explain extended select b,(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2) from t4; explain extended select b,(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2) from t4;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t4 ALL NULL NULL NULL NULL 3 1 PRIMARY t4 ALL NULL NULL NULL NULL 3

View File

@ -46,6 +46,7 @@ db CREATE TABLE `db` (
`Alter_routine_priv` enum('N','Y') character set utf8 NOT NULL default 'N', `Alter_routine_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
`Execute_priv` enum('N','Y') character set utf8 NOT NULL default 'N', `Execute_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
`Event_priv` enum('N','Y') character set utf8 NOT NULL default 'N', `Event_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
`Trigger_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
PRIMARY KEY (`Host`,`Db`,`User`), PRIMARY KEY (`Host`,`Db`,`User`),
KEY `User` (`User`) KEY `User` (`User`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Database privileges' ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Database privileges'
@ -71,6 +72,7 @@ host CREATE TABLE `host` (
`Create_routine_priv` enum('N','Y') character set utf8 NOT NULL default 'N', `Create_routine_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
`Alter_routine_priv` enum('N','Y') character set utf8 NOT NULL default 'N', `Alter_routine_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
`Execute_priv` enum('N','Y') character set utf8 NOT NULL default 'N', `Execute_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
`Trigger_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
PRIMARY KEY (`Host`,`Db`) PRIMARY KEY (`Host`,`Db`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Host privileges; Merged with database privileges' ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Host privileges; Merged with database privileges'
show create table user; show create table user;
@ -106,6 +108,7 @@ user CREATE TABLE `user` (
`Alter_routine_priv` enum('N','Y') character set utf8 NOT NULL default 'N', `Alter_routine_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
`Create_user_priv` enum('N','Y') character set utf8 NOT NULL default 'N', `Create_user_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
`Event_priv` enum('N','Y') character set utf8 NOT NULL default 'N', `Event_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
`Trigger_priv` enum('N','Y') character set utf8 NOT NULL default 'N',
`ssl_type` enum('','ANY','X509','SPECIFIED') character set utf8 NOT NULL default '', `ssl_type` enum('','ANY','X509','SPECIFIED') character set utf8 NOT NULL default '',
`ssl_cipher` blob NOT NULL, `ssl_cipher` blob NOT NULL,
`x509_issuer` blob NOT NULL, `x509_issuer` blob NOT NULL,
@ -134,7 +137,7 @@ tables_priv CREATE TABLE `tables_priv` (
`Table_name` char(64) collate utf8_bin NOT NULL default '', `Table_name` char(64) collate utf8_bin NOT NULL default '',
`Grantor` char(77) collate utf8_bin NOT NULL default '', `Grantor` char(77) collate utf8_bin NOT NULL default '',
`Timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, `Timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
`Table_priv` set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view') character set utf8 NOT NULL default '', `Table_priv` set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view','Trigger') character set utf8 NOT NULL default '',
`Column_priv` set('Select','Insert','Update','References') character set utf8 NOT NULL default '', `Column_priv` set('Select','Insert','Update','References') character set utf8 NOT NULL default '',
PRIMARY KEY (`Host`,`Db`,`User`,`Table_name`), PRIMARY KEY (`Host`,`Db`,`User`,`Table_name`),
KEY `Grantor` (`Grantor`) KEY `Grantor` (`Grantor`)

View File

@ -240,6 +240,28 @@ t3 CREATE TABLE `t3` (
`d` double(22,9) default NULL `d` double(22,9) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1, t2, t3; drop table t1, t2, t3;
create table t1 select 105213674794682365.00 + 0.0 x;
show warnings;
Level Code Message
desc t1;
Field Type Null Key Default Extra
x decimal(21,2) unsigned NO 0.00
drop table t1;
create table t1 select 0.0 x;
desc t1;
Field Type Null Key Default Extra
x decimal(2,1) unsigned NO 0.0
create table t2 select 105213674794682365.00 y;
desc t2;
Field Type Null Key Default Extra
y decimal(20,2) unsigned NO 0.00
create table t3 select x+y a from t1,t2;
show warnings;
Level Code Message
desc t3;
Field Type Null Key Default Extra
a decimal(21,2) unsigned NO 0.00
drop table t1,t2,t3;
create table t1 (s1 float(0,2)); create table t1 (s1 float(0,2));
ERROR 42000: For float(M,D), double(M,D) or decimal(M,D), M must be >= D (column 's1'). ERROR 42000: For float(M,D), double(M,D) or decimal(M,D), M must be >= D (column 's1').
create table t1 (s1 float(1,2)); create table t1 (s1 float(1,2));

View File

@ -415,3 +415,10 @@ t1 CREATE TABLE `t1` (
KEY `index1` (`f1`(10)) KEY `index1` (`f1`(10))
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1; drop table t1;
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(f1 VARCHAR(100) DEFAULT 'test');
INSERT INTO t1 VALUES(SUBSTR(f1, 1, 3));
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(f1 CHAR(100) DEFAULT 'test');
INSERT INTO t1 VALUES(SUBSTR(f1, 1, 3));
DROP TABLE IF EXISTS t1;

View File

@ -29,8 +29,6 @@ rpl_sp : Bug #16456
ndb_autodiscover : Needs to be fixed w.r.t binlog ndb_autodiscover : Needs to be fixed w.r.t binlog
ndb_autodiscover2 : Needs to be fixed w.r.t binlog ndb_autodiscover2 : Needs to be fixed w.r.t binlog
ndb_blob : BLOB replication causes core in master1 (Pekka will fix) ndb_blob : BLOB replication causes core in master1 (Pekka will fix)
system_mysql_db : Needs fixing
system_mysql_db_fix : Needs fixing
#ndb_alter_table_row : sometimes wrong error 1015!=1046 #ndb_alter_table_row : sometimes wrong error 1015!=1046
ndb_gis : garbled msgs from corrupt THD* ndb_gis : garbled msgs from corrupt THD*
ndb_binlog_ddl_multi : Bug #17038 ndb_binlog_ddl_multi : Bug #17038

View File

@ -209,6 +209,14 @@ insert into t1 values('test test '),('test'),('test'),('test'),
('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'), ('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'),
('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test'); ('test'),('test'),('test'),('test'),('test'),('test'),('test'),('test');
delete from t1 limit 1; delete from t1 limit 1;
#
# BUG#16489: utf8 + fulltext leads to corrupt index file.
#
truncate table t1;
insert into t1 values('ab c d');
update t1 set a='ab c d';
select * from t1 where match a against('ab c' in boolean mode);
drop table t1; drop table t1;
set names latin1; set names latin1;

View File

@ -121,7 +121,9 @@ drop table t1;
# #
# InnoDB is required to reproduce the fault, but it is okay if we default to # InnoDB is required to reproduce the fault, but it is okay if we default to
# MyISAM when testing. # MyISAM when testing.
--disable_warnings
create table t1 (a varchar(90), ts datetime not null, index (a)) engine=innodb default charset=utf8; create table t1 (a varchar(90), ts datetime not null, index (a)) engine=innodb default charset=utf8;
--enable_warnings
insert into t1 values ('http://www.foo.com/', now()); insert into t1 values ('http://www.foo.com/', now());
select a from t1 where a='http://www.foo.com/' order by abs(timediff(ts, 0)); select a from t1 where a='http://www.foo.com/' order by abs(timediff(ts, 0));
drop table t1; drop table t1;

View File

@ -794,6 +794,29 @@ DROP TABLE t1;
DROP VIEW v1; DROP VIEW v1;
DROP FUNCTION func1; DROP FUNCTION func1;
DROP FUNCTION func2; DROP FUNCTION func2;
#
# Bug #15851 Unlistable directories yield no info from information_schema
#
create database mysqltest;
create table mysqltest.t1(a int);
--exec chmod -r $MYSQL_TEST_DIR/var/master-data/mysqltest
select table_schema from information_schema.tables where table_schema='mysqltest';
--exec chmod +r $MYSQL_TEST_DIR/var/master-data/mysqltest
drop database mysqltest;
#
# Bug#15307 GROUP_CONCAT() with ORDER BY returns empty set on information_schema
#
select column_type, group_concat(table_schema, '.', table_name), count(*) as num
from information_schema.columns where
table_schema='information_schema' and
(column_type = 'varchar(7)' or column_type = 'varchar(20)')
group by column_type order by num;
#
# End of 5.0 tests.
#
# Show engines # Show engines
# #

View File

@ -0,0 +1 @@
--replicate-wild-do-table=d1.%

View File

@ -0,0 +1,44 @@
# Let's verify that multi-update is not always skipped by slave if
# some replicate-* rules exist.
# (BUG#15699)
source include/master-slave.inc;
### Clean-up
connection master;
--disable_warnings
drop database if exists d1;
drop database if exists d2;
connection slave;
drop database if exists d2;
--enable_warnings
### Test
connection master;
create database d1; # accepted by slave
create table d1.t0 (id int);
create database d2; # ignored by slave
use d2;
create table t1 (id int);
create table t2 (id int);
insert into t1 values (1), (2), (3), (4), (5);
insert into t2 select id + 3 from t1;
# a problematic query which must be filter out by slave
update t1 join t2 using (id) set t1.id = 0;
insert into d1.t0 values (0); # replication works
sync_slave_with_master;
use d1;
#connection slave;
select * from t0 where id=0; # must find
### Clean-up
connection master;
drop database d1;
drop database d2;
# End of test

View File

@ -403,6 +403,42 @@ sync_slave_with_master;
connection slave; connection slave;
select * from t1; select * from t1;
#
# Bug#16621 "INSERTs in Stored Procedures causes data corruption in the Binary
# Log for 5.0.18"
#
# Prepare environment.
connection master;
--disable_warnings
DROP PROCEDURE IF EXISTS p1;
DROP TABLE IF EXISTS t1;
--enable_warnings
# Test case.
CREATE TABLE t1(col VARCHAR(10));
CREATE PROCEDURE p1(arg VARCHAR(10))
INSERT INTO t1 VALUES(arg);
CALL p1('test');
SELECT * FROM t1;
sync_slave_with_master;
connection slave;
SELECT * FROM t1;
# Cleanup.
connection master;
DROP PROCEDURE p1;
# cleanup # cleanup
connection master; connection master;
drop table t1; drop table t1;

View File

@ -1534,6 +1534,7 @@ drop procedure bug13012_1|
drop function bug13012_2| drop function bug13012_2|
delimiter ;| delimiter ;|
#
# BUG#11555 "Stored procedures: current SP tables locking make # BUG#11555 "Stored procedures: current SP tables locking make
# impossible view security". We should not expose names of tables # impossible view security". We should not expose names of tables
# which are implicitly used by view (via stored routines/triggers). # which are implicitly used by view (via stored routines/triggers).
@ -1594,7 +1595,33 @@ drop function bug11555_1;
drop table t1; drop table t1;
drop view v1; drop view v1;
#
# BUG#15658: Server crashes after creating function as empty string
#
--disable_warnings
drop procedure if exists ` bug15658`;
--enable_warnings
--error ER_SP_WRONG_NAME
create procedure ``() select 1;
--error ER_SP_WRONG_NAME
create procedure ` `() select 1;
--error ER_SP_WRONG_NAME
create procedure `bug15658 `() select 1;
--error ER_WRONG_DB_NAME
create procedure ``.bug15658() select 1;
--error ER_WRONG_DB_NAME
create procedure `x `.bug15658() select 1;
# This should work
create procedure ` bug15658`() select 1;
call ` bug15658`();
--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
show procedure status;
drop procedure ` bug15658`;
#
# BUG#NNNN: New bug synopsis # BUG#NNNN: New bug synopsis
# #
#--disable_warnings #--disable_warnings

View File

@ -437,4 +437,48 @@ disconnect test_user_12812|
DROP USER user_bug12812@localhost| DROP USER user_bug12812@localhost|
drop function bug12812| drop function bug12812|
delimiter ;| delimiter ;|
#
# BUG#14834: Server denies to execute Stored Procedure
#
# The problem here was with '_' in the database name.
#
create database db_bug14834;
create user user1_bug14834@localhost identified by '';
# The exact name of the database (no wildcard)
grant all on `db\_bug14834`.* to user1_bug14834@localhost;
create user user2_bug14834@localhost identified by '';
# The exact name of the database (no wildcard)
grant all on `db\_bug14834`.* to user2_bug14834@localhost;
create user user3_bug14834@localhost identified by '';
# Wildcards in the database name
grant all on `db__ug14834`.* to user3_bug14834@localhost;
connect (user1_bug14834,localhost,user1_bug14834,,db_bug14834);
# Create the procedure and check that we can call it
create procedure p_bug14834() select user(), current_user();
call p_bug14834();
connect (user2_bug14834,localhost,user2_bug14834,,db_bug14834);
# This didn't work before
call p_bug14834();
connect (user3_bug14834,localhost,user3_bug14834,,db_bug14834);
# Should also work
call p_bug14834();
# Cleanup
connection default;
disconnect user1_bug14834;
disconnect user2_bug14834;
disconnect user3_bug14834;
drop user user1_bug14834@localhost;
drop user user2_bug14834@localhost;
drop user user3_bug14834@localhost;
drop database db_bug14834;
# End of 5.0 bugs. # End of 5.0 bugs.

View File

@ -1419,9 +1419,9 @@ drop table t4|
# fac # fac
--disable_warnings --disable_warnings
drop table if exists fac| drop table if exists t3|
--enable_warnings --enable_warnings
create table fac (n int unsigned not null primary key, f bigint unsigned)| create table t3 (n int unsigned not null primary key, f bigint unsigned)|
--disable_warnings --disable_warnings
drop procedure if exists ifac| drop procedure if exists ifac|
@ -1435,15 +1435,15 @@ begin
end if; end if;
while i <= n do while i <= n do
begin begin
insert into test.fac values (i, fac(i)); insert into test.t3 values (i, fac(i));
set i = i + 1; set i = i + 1;
end; end;
end while; end while;
end| end|
call ifac(20)| call ifac(20)|
select * from fac| select * from t3|
drop table fac| drop table t3|
--replace_column 4 'root@localhost' 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00' --replace_column 4 'root@localhost' 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
show function status like '%f%'| show function status like '%f%'|
drop procedure ifac| drop procedure ifac|
@ -1455,15 +1455,15 @@ show function status like '%f%'|
# primes # primes
--disable_warnings --disable_warnings
drop table if exists primes| drop table if exists t3|
--enable_warnings --enable_warnings
create table primes ( create table t3 (
i int unsigned not null primary key, i int unsigned not null primary key,
p bigint unsigned not null p bigint unsigned not null
)| )|
insert into primes values insert into t3 values
( 0, 3), ( 1, 5), ( 2, 7), ( 3, 11), ( 4, 13), ( 0, 3), ( 1, 5), ( 2, 7), ( 3, 11), ( 4, 13),
( 5, 17), ( 6, 19), ( 7, 23), ( 8, 29), ( 9, 31), ( 5, 17), ( 6, 19), ( 7, 23), ( 8, 29), ( 9, 31),
(10, 37), (11, 41), (12, 43), (13, 47), (14, 53), (10, 37), (11, 41), (12, 43), (13, 47), (14, 53),
@ -1492,7 +1492,7 @@ begin
begin begin
declare p bigint unsigned; declare p bigint unsigned;
select t.p into p from test.primes t where t.i = s; select t.p into p from test.t3 t where t.i = s;
if b+p > r then if b+p > r then
set pp = 1; set pp = 1;
leave again; leave again;
@ -1523,7 +1523,7 @@ begin
call opp(p, pp); call opp(p, pp);
if pp then if pp then
insert into test.primes values (i, p); insert into test.t3 values (i, p);
set i = i+1; set i = i+1;
end if; end if;
set p = p+2; set p = p+2;
@ -1545,8 +1545,8 @@ call ip(200)|
# 45 211 # 45 211
# 100 557 # 100 557
# 199 1229 # 199 1229
select * from primes where i=45 or i=100 or i=199| select * from t3 where i=45 or i=100 or i=199|
drop table primes| drop table t3|
drop procedure opp| drop procedure opp|
drop procedure ip| drop procedure ip|
--replace_column 4 'root@localhost' 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00' --replace_column 4 'root@localhost' 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
@ -1556,9 +1556,9 @@ show procedure status like '%p%'|
# Fibonacci, for recursion test. (Yet Another Numerical series :) # Fibonacci, for recursion test. (Yet Another Numerical series :)
# #
--disable_warnings --disable_warnings
drop table if exists fib| drop table if exists t3|
--enable_warnings --enable_warnings
create table fib ( f bigint unsigned not null )| create table t3 ( f bigint unsigned not null )|
# We deliberately do it the awkward way, fetching the last two # We deliberately do it the awkward way, fetching the last two
# values from the table, in order to exercise various statements # values from the table, in order to exercise various statements
@ -1571,13 +1571,13 @@ begin
if n > 1 then if n > 1 then
begin begin
declare x, y bigint unsigned; declare x, y bigint unsigned;
declare c cursor for select f from fib order by f desc limit 2; declare c cursor for select f from t3 order by f desc limit 2;
open c; open c;
fetch c into y; fetch c into y;
fetch c into x; fetch c into x;
close c; close c;
insert into fib values (x+y); insert into t3 values (x+y);
call fib(n-1); call fib(n-1);
end; end;
end if; end if;
@ -1588,22 +1588,23 @@ set @@max_sp_recursion_depth= 20|
# Minimum test: recursion of 3 levels # Minimum test: recursion of 3 levels
insert into fib values (0), (1)| insert into t3 values (0), (1)|
call fib(3)| call fib(3)|
select * from fib order by f asc| select * from t3 order by f asc|
delete from fib| delete from t3|
# Original test: 20 levels (may run into memory limits!) # The original test, 20 levels, ran into memory limits on some machines
# and builds. Try 10 instead...
insert into fib values (0), (1)| insert into t3 values (0), (1)|
call fib(20)| call fib(10)|
select * from fib order by f asc| select * from t3 order by f asc|
drop table fib| drop table t3|
drop procedure fib| drop procedure fib|
set @@max_sp_recursion_depth= 0| set @@max_sp_recursion_depth= 0|

View File

@ -5,7 +5,7 @@
-- source include/have_innodb.inc -- source include/have_innodb.inc
--disable_warnings --disable_warnings
drop table if exists t1, t2; drop table if exists t1, t2, t3;
--enable_warnings --enable_warnings
delimiter |; delimiter |;

View File

@ -159,6 +159,23 @@ show create table t3;
drop table t1, t2, t3; drop table t1, t2, t3;
#
# Bug #9855 (inconsistent column type for create select
#
create table t1 select 105213674794682365.00 + 0.0 x;
show warnings;
desc t1;
drop table t1;
create table t1 select 0.0 x;
desc t1;
create table t2 select 105213674794682365.00 y;
desc t2;
create table t3 select x+y a from t1,t2;
show warnings;
desc t3;
drop table t1,t2,t3;
# End of 4.1 tests # End of 4.1 tests
# #

View File

@ -130,3 +130,19 @@ show create table t1;
alter table t1 modify f1 tinytext; alter table t1 modify f1 tinytext;
show create table t1; show create table t1;
drop table t1; drop table t1;
#
# BUG#15588: String overrun
#
--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings
CREATE TABLE t1(f1 VARCHAR(100) DEFAULT 'test');
INSERT INTO t1 VALUES(SUBSTR(f1, 1, 3));
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(f1 CHAR(100) DEFAULT 'test');
INSERT INTO t1 VALUES(SUBSTR(f1, 1, 3));
DROP TABLE IF EXISTS t1;

View File

@ -197,7 +197,7 @@ int modify_defaults_file(const char *file_location, const char *option,
goto err; goto err;
} }
if (my_fclose(cnf_file, MYF(MY_WME))) if (my_fclose(cnf_file, MYF(MY_WME)))
goto err; DBUG_RETURN(1);
my_free(file_buffer, MYF(0)); my_free(file_buffer, MYF(0));
DBUG_RETURN(0); DBUG_RETURN(0);

View File

@ -79,7 +79,7 @@ my_off_t my_b_safe_tell(IO_CACHE *info)
void my_b_seek(IO_CACHE *info,my_off_t pos) void my_b_seek(IO_CACHE *info,my_off_t pos)
{ {
my_off_t offset; my_off_t offset;
DBUG_ENTER("my_b_seek"); DBUG_ENTER("my_b_seek");
DBUG_PRINT("enter",("pos: %lu", (ulong) pos)); DBUG_PRINT("enter",("pos: %lu", (ulong) pos));
@ -91,10 +91,10 @@ void my_b_seek(IO_CACHE *info,my_off_t pos)
b) see if there is a better way to make it work b) see if there is a better way to make it work
*/ */
if (info->type == SEQ_READ_APPEND) if (info->type == SEQ_READ_APPEND)
flush_io_cache(info); VOID(flush_io_cache(info));
offset=(pos - info->pos_in_file); offset=(pos - info->pos_in_file);
if (info->type == READ_CACHE || info->type == SEQ_READ_APPEND) if (info->type == READ_CACHE || info->type == SEQ_READ_APPEND)
{ {
/* TODO: explain why this works if pos < info->pos_in_file */ /* TODO: explain why this works if pos < info->pos_in_file */
@ -119,7 +119,7 @@ void my_b_seek(IO_CACHE *info,my_off_t pos)
info->write_pos = info->write_buffer + offset; info->write_pos = info->write_buffer + offset;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
flush_io_cache(info); VOID(flush_io_cache(info));
/* Correct buffer end so that we write in increments of IO_SIZE */ /* Correct buffer end so that we write in increments of IO_SIZE */
info->write_end=(info->write_buffer+info->buffer_length- info->write_end=(info->write_buffer+info->buffer_length-
(pos & (IO_SIZE-1))); (pos & (IO_SIZE-1)));

View File

@ -114,7 +114,7 @@ my_bool bitmap_init(MY_BITMAP *map, uint32 *buf, uint n_bits,
#endif #endif
; ;
if (!(buf= (uint32*) my_malloc(size_in_bytes, MYF(MY_WME)))) if (!(buf= (uint32*) my_malloc(size_in_bytes, MYF(MY_WME))))
return 1; DBUG_RETURN(1);
} }
#ifdef THREAD #ifdef THREAD
else else

View File

@ -189,7 +189,10 @@ int my_error_register(const char **errmsgs, int first, int last)
/* Error numbers must be unique. No overlapping is allowed. */ /* Error numbers must be unique. No overlapping is allowed. */
if (*search_meh_pp && ((*search_meh_pp)->meh_first <= last)) if (*search_meh_pp && ((*search_meh_pp)->meh_first <= last))
{
my_free((gptr)meh_p, MYF(0));
return 1; return 1;
}
/* Insert header into the chain. */ /* Insert header into the chain. */
meh_p->meh_next= *search_meh_pp; meh_p->meh_next= *search_meh_pp;

View File

@ -170,6 +170,8 @@ MY_DIR *my_dir(const char *path, myf MyFlags)
bzero(finfo.mystat, sizeof(MY_STAT)); bzero(finfo.mystat, sizeof(MY_STAT));
VOID(strmov(tmp_file,dp->d_name)); VOID(strmov(tmp_file,dp->d_name));
VOID(my_stat(tmp_path, finfo.mystat, MyFlags)); VOID(my_stat(tmp_path, finfo.mystat, MyFlags));
if (!(finfo.mystat->st_mode & MY_S_IREAD))
continue;
} }
else else
finfo.mystat= NULL; finfo.mystat= NULL;

View File

@ -674,5 +674,9 @@ ALTER TABLE event ADD sql_mode
SET @hadTriggerPriv := 0; SET @hadTriggerPriv := 0;
SELECT @hadTriggerPriv :=1 FROM user WHERE Trigger_priv LIKE '%'; SELECT @hadTriggerPriv :=1 FROM user WHERE Trigger_priv LIKE '%';
ALTER TABLE user add Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL; ALTER TABLE user ADD Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Event_priv;
ALTER TABLE host ADD Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL;
ALTER TABLE db ADD Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL;
ALTER TABLE tables_priv MODIFY Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view','Trigger') COLLATE utf8_general_ci DEFAULT '' NOT NULL;
UPDATE user SET Trigger_priv=Super_priv WHERE @hadTriggerPriv = 0; UPDATE user SET Trigger_priv=Super_priv WHERE @hadTriggerPriv = 0;

View File

@ -107,7 +107,7 @@ Token shift_token(const char **text, uint *word_len)
int get_text_id(const char **text, uint *word_len, const char **id) int get_text_id(const char **text, uint *word_len, const char **id)
{ {
get_word(text, word_len); get_word(text, word_len);
if (word_len == 0) if (*word_len == 0)
return 1; return 1;
*id= *text; *id= *text;
return 0; return 0;

View File

@ -599,7 +599,7 @@ net_safe_read(MYSQL *mysql)
DBUG_PRINT("error",("Wrong connection or packet. fd: %s len: %d", DBUG_PRINT("error",("Wrong connection or packet. fd: %s len: %d",
vio_description(net->vio),len)); vio_description(net->vio),len));
#ifdef MYSQL_SERVER #ifdef MYSQL_SERVER
if (vio_was_interrupted(net->vio)) if (net->vio && vio_was_interrupted(net->vio))
return (packet_error); return (packet_error);
#endif /*MYSQL_SERVER*/ #endif /*MYSQL_SERVER*/
end_server(mysql); end_server(mysql);

View File

@ -1565,7 +1565,6 @@ Field *Field::new_key_field(MEM_ROOT *root, struct st_table *new_table,
bool Field::quote_data(String *unquoted_string) bool Field::quote_data(String *unquoted_string)
{ {
char escaped_string[IO_SIZE]; char escaped_string[IO_SIZE];
char *unquoted_string_buffer= (char *)(unquoted_string->ptr());
DBUG_ENTER("Field::quote_data"); DBUG_ENTER("Field::quote_data");
if (!needs_quotes()) if (!needs_quotes())
@ -4545,8 +4544,6 @@ int Field_timestamp::store(const char *from,uint len,CHARSET_INFO *cs)
error= 1; error= 1;
} }
} }
if (error > 1)
error= 2;
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
if (table->s->db_low_byte_first) if (table->s->db_low_byte_first)
@ -5880,7 +5877,7 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs)
field_length/ field_length/
field_charset->mbmaxlen, field_charset->mbmaxlen,
&well_formed_error); &well_formed_error);
memcpy(ptr,from,copy_length); memmove(ptr, from, copy_length);
/* Append spaces if the string was shorter than the field. */ /* Append spaces if the string was shorter than the field. */
if (copy_length < field_length) if (copy_length < field_length)
@ -6296,7 +6293,7 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs)
field_length/ field_length/
field_charset->mbmaxlen, field_charset->mbmaxlen,
&well_formed_error); &well_formed_error);
memcpy(ptr + length_bytes, from, copy_length); memmove(ptr + length_bytes, from, copy_length);
if (length_bytes == 1) if (length_bytes == 1)
*ptr= (uchar) copy_length; *ptr= (uchar) copy_length;
else else
@ -7113,7 +7110,7 @@ void Field_blob::get_key_image(char *buff, uint length, imagetype type)
} }
get_ptr(&blob); get_ptr(&blob);
gobj= Geometry::construct(&buffer, blob, blob_length); gobj= Geometry::construct(&buffer, blob, blob_length);
if (gobj->get_mbr(&mbr, &dummy)) if (!gobj || gobj->get_mbr(&mbr, &dummy))
bzero(buff, SIZEOF_STORED_DOUBLE*4); bzero(buff, SIZEOF_STORED_DOUBLE*4);
else else
{ {
@ -7442,7 +7439,7 @@ void Field_geom::get_key_image(char *buff, uint length, imagetype type)
} }
get_ptr(&blob); get_ptr(&blob);
gobj= Geometry::construct(&buffer, blob, blob_length); gobj= Geometry::construct(&buffer, blob, blob_length);
if (gobj->get_mbr(&mbr, &dummy)) if (!gobj || gobj->get_mbr(&mbr, &dummy))
bzero(buff, SIZEOF_STORED_DOUBLE*4); bzero(buff, SIZEOF_STORED_DOUBLE*4);
else else
{ {
@ -8239,16 +8236,13 @@ const char *Field_bit::unpack(char *to, const char *from)
*/ */
Field_bit_as_char::Field_bit_as_char(char *ptr_arg, uint32 len_arg, Field_bit_as_char::Field_bit_as_char(char *ptr_arg, uint32 len_arg,
uchar *null_ptr_arg, uchar null_bit_arg, uchar *null_ptr_arg, uchar null_bit_arg,
uchar *bit_ptr_arg, uchar bit_ofs_arg, enum utype unireg_check_arg,
enum utype unireg_check_arg,
const char *field_name_arg) const char *field_name_arg)
:Field_bit(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, bit_ptr_arg, :Field_bit(ptr_arg, len_arg, null_ptr_arg, null_bit_arg, 0, 0,
bit_ofs_arg, unireg_check_arg, field_name_arg), unireg_check_arg, field_name_arg),
create_length(len_arg) create_length(len_arg)
{ {
bit_ptr= 0;
bit_ofs= 0;
bit_len= 0; bit_len= 0;
field_length= ((len_arg + 7) & ~7) / 8; field_length= ((len_arg + 7) & ~7) / 8;
} }
@ -8950,10 +8944,10 @@ Field *make_field(TABLE_SHARE *share, char *ptr, uint32 field_length,
field_charset); field_charset);
case FIELD_TYPE_BIT: case FIELD_TYPE_BIT:
return f_bit_as_char(pack_flag) ? return f_bit_as_char(pack_flag) ?
new Field_bit_as_char(ptr, field_length, null_pos, null_bit, new Field_bit_as_char(ptr, field_length, null_pos, null_bit,
bit_ptr, bit_offset, unireg_check, field_name) : unireg_check, field_name) :
new Field_bit(ptr, field_length, null_pos, null_bit, bit_ptr, new Field_bit(ptr, field_length, null_pos, null_bit, bit_ptr,
bit_offset, unireg_check, field_name); bit_offset, unireg_check, field_name);
default: // Impossible (Wrong version) default: // Impossible (Wrong version)
break; break;

View File

@ -1373,12 +1373,12 @@ public:
} }
}; };
class Field_bit_as_char: public Field_bit { class Field_bit_as_char: public Field_bit {
public: public:
uchar create_length; uchar create_length;
Field_bit_as_char(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, Field_bit_as_char(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg, uchar *bit_ptr_arg, uchar bit_ofs_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg); enum utype unireg_check_arg, const char *field_name_arg);
enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; }
uint32 max_length() { return (uint32) create_length; } uint32 max_length() { return (uint32) create_length; }

View File

@ -139,6 +139,10 @@ static HASH archive_open_tables;
/* Static declarations for handerton */ /* Static declarations for handerton */
static handler *archive_create_handler(TABLE_SHARE *table); static handler *archive_create_handler(TABLE_SHARE *table);
/*
Number of rows that will force a bulk insert.
*/
#define ARCHIVE_MIN_ROWS_TO_USE_BULK_INSERT 2
/* dummy handlerton - only to have something to return from archive_db_init */ /* dummy handlerton - only to have something to return from archive_db_init */
@ -1302,7 +1306,8 @@ void ha_archive::info(uint flag)
void ha_archive::start_bulk_insert(ha_rows rows) void ha_archive::start_bulk_insert(ha_rows rows)
{ {
DBUG_ENTER("ha_archive::start_bulk_insert"); DBUG_ENTER("ha_archive::start_bulk_insert");
bulk_insert= TRUE; if (!rows || rows >= ARCHIVE_MIN_ROWS_TO_USE_BULK_INSERT)
bulk_insert= TRUE;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }

View File

@ -286,7 +286,8 @@ int ha_myisam::dump(THD* thd, int fd)
if (fd < 0) if (fd < 0)
{ {
my_net_write(net, "", 0); if (my_net_write(net, "", 0))
error = errno ? errno : EPIPE;
net_flush(net); net_flush(net);
} }
@ -420,12 +421,14 @@ int ha_myisam::check(THD* thd, HA_CHECK_OPT* check_opt)
{ {
uint old_testflag=param.testflag; uint old_testflag=param.testflag;
param.testflag|=T_MEDIUM; param.testflag|=T_MEDIUM;
init_io_cache(&param.read_cache, file->dfile, if (!(error= init_io_cache(&param.read_cache, file->dfile,
my_default_record_cache_size, READ_CACHE, my_default_record_cache_size, READ_CACHE,
share->pack.header_length, 1, MYF(MY_WME)); share->pack.header_length, 1, MYF(MY_WME))))
error |= chk_data_link(&param, file, param.testflag & T_EXTEND); {
end_io_cache(&(param.read_cache)); error= chk_data_link(&param, file, param.testflag & T_EXTEND);
param.testflag=old_testflag; end_io_cache(&(param.read_cache));
}
param.testflag= old_testflag;
} }
} }
if (!error) if (!error)

View File

@ -985,7 +985,7 @@ Item_case_expr::this_item_addr(THD *thd, Item **)
void Item_case_expr::print(String *str) void Item_case_expr::print(String *str)
{ {
str->append(STRING_WITH_LEN("case_expr@")); VOID(str->append(STRING_WITH_LEN("case_expr@")));
str->qs_append(m_case_expr_id); str->qs_append(m_case_expr_id);
} }
@ -3868,7 +3868,7 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table, bool fixed_length)
name); name);
break; break;
case MYSQL_TYPE_BIT: case MYSQL_TYPE_BIT:
field= new Field_bit_as_char(NULL, max_length, null_ptr, 0, NULL, 0, field= new Field_bit_as_char(NULL, max_length, null_ptr, 0,
Field::NONE, name); Field::NONE, name);
break; break;
default: default:

View File

@ -431,12 +431,19 @@ my_decimal *Item_real_func::val_decimal(my_decimal *decimal_value)
void Item_func::fix_num_length_and_dec() void Item_func::fix_num_length_and_dec()
{ {
decimals= 0; uint fl_length= 0;
decimals=0;
for (uint i=0 ; i < arg_count ; i++) for (uint i=0 ; i < arg_count ; i++)
{ {
set_if_bigger(decimals, args[i]->decimals); set_if_bigger(decimals,args[i]->decimals);
set_if_bigger(fl_length, args[i]->max_length);
}
max_length=float_length(decimals);
if (fl_length > max_length)
{
decimals= NOT_FIXED_DEC;
max_length= float_length(NOT_FIXED_DEC);
} }
max_length= float_length(decimals);
} }

View File

@ -3342,6 +3342,10 @@ void Intvar_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
case INSERT_ID_EVENT: case INSERT_ID_EVENT:
msg="INSERT_ID"; msg="INSERT_ID";
break; break;
case INVALID_INT_EVENT:
default: // cannot happen
msg="INVALID_INT";
break;
} }
fprintf(file, "%s=%s;\n", msg, llstr(val,llbuff)); fprintf(file, "%s=%s;\n", msg, llstr(val,llbuff));
fflush(file); fflush(file);

View File

@ -5130,7 +5130,7 @@ Disable with --skip-innodb-doublewrite.", (gptr*) &innobase_use_doublewrite,
"Set to 0 (write and flush once per second), 1 (write and flush at each commit) or 2 (write at commit, flush once per second).", "Set to 0 (write and flush once per second), 1 (write and flush at each commit) or 2 (write at commit, flush once per second).",
(gptr*) &innobase_flush_log_at_trx_commit, (gptr*) &innobase_flush_log_at_trx_commit,
(gptr*) &innobase_flush_log_at_trx_commit, (gptr*) &innobase_flush_log_at_trx_commit,
0, GET_UINT, OPT_ARG, 1, 0, 2, 0, 0, 0}, 0, GET_ULONG, OPT_ARG, 1, 0, 2, 0, 0, 0},
{"innodb_flush_method", OPT_INNODB_FLUSH_METHOD, {"innodb_flush_method", OPT_INNODB_FLUSH_METHOD,
"With which method to flush data.", (gptr*) &innobase_unix_file_flush_method, "With which method to flush data.", (gptr*) &innobase_unix_file_flush_method,
(gptr*) &innobase_unix_file_flush_method, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, (gptr*) &innobase_unix_file_flush_method, 0, GET_STR, REQUIRED_ARG, 0, 0, 0,

View File

@ -753,7 +753,6 @@ SQL_SELECT *make_select(TABLE *head, table_map const_tables,
table_map read_tables, COND *conds, table_map read_tables, COND *conds,
bool allow_null_cond, bool allow_null_cond,
int *error) int *error)
{ {
SQL_SELECT *select; SQL_SELECT *select;
DBUG_ENTER("make_select"); DBUG_ENTER("make_select");
@ -7059,10 +7058,7 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
if (!quick) if (!quick)
return 0; /* no ranges found */ return 0; /* no ranges found */
if (quick->init()) if (quick->init())
{
delete quick;
goto err; goto err;
}
quick->records= records; quick->records= records;
if (cp_buffer_from_ref(thd,ref) && thd->is_fatal_error || if (cp_buffer_from_ref(thd,ref) && thd->is_fatal_error ||
@ -8404,7 +8400,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
ha_rows cur_records; ha_rows cur_records;
SEL_ARG *cur_index_tree= NULL; SEL_ARG *cur_index_tree= NULL;
ha_rows cur_quick_prefix_records= 0; ha_rows cur_quick_prefix_records= 0;
uint cur_param_idx; uint cur_param_idx=MAX_KEY;
key_map cur_used_key_parts; key_map cur_used_key_parts;
uint pk= param->table->s->primary_key; uint pk= param->table->s->primary_key;
@ -8620,6 +8616,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
*/ */
if (cur_read_cost < best_read_cost - (DBL_EPSILON * cur_read_cost)) if (cur_read_cost < best_read_cost - (DBL_EPSILON * cur_read_cost))
{ {
DBUG_ASSERT(tree != 0 || cur_param_idx == MAX_KEY);
index_info= cur_index_info; index_info= cur_index_info;
index= cur_index; index= cur_index;
best_read_cost= cur_read_cost; best_read_cost= cur_read_cost;

View File

@ -706,7 +706,7 @@ class SQL_SELECT :public Sql_alloc {
class FT_SELECT: public QUICK_RANGE_SELECT { class FT_SELECT: public QUICK_RANGE_SELECT {
public: public:
FT_SELECT(THD *thd, TABLE *table, uint key) : FT_SELECT(THD *thd, TABLE *table, uint key) :
QUICK_RANGE_SELECT (thd, table, key, 1) { init(); } QUICK_RANGE_SELECT (thd, table, key, 1) { VOID(init()); }
~FT_SELECT() { file->ft_end(); } ~FT_SELECT() { file->ft_end(); }
int init() { return error=file->ft_init(); } int init() { return error=file->ft_init(); }
int reset() { return 0; } int reset() { return 0; }

View File

@ -601,9 +601,23 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
else else
{ {
/* With conversion */ /* With conversion */
uint max_char_len;
int2store(pos, thd_charset->number); int2store(pos, thd_charset->number);
uint char_len= field.length / item->collation.collation->mbmaxlen; /*
int4store(pos+2, char_len * thd_charset->mbmaxlen); For TEXT/BLOB columns, field_length describes the maximum data
length in bytes. There is no limit to the number of characters
that a TEXT column can store, as long as the data fits into
the designated space.
For the rest of textual columns, field_length is evaluated as
char_count * mbmaxlen, where character count is taken from the
definition of the column. In other words, the maximum number
of characters here is limited by the column definition.
*/
max_char_len= (field.type >= (int) MYSQL_TYPE_TINY_BLOB &&
field.type <= (int) MYSQL_TYPE_BLOB) ?
field.length / item->collation.collation->mbminlen :
field.length / item->collation.collation->mbmaxlen;
int4store(pos+2, max_char_len * thd_charset->mbmaxlen);
} }
pos[6]= field.type; pos[6]= field.type;
int2store(pos+7,field.flags); int2store(pos+7,field.flags);

View File

@ -930,7 +930,8 @@ bool load_master_data(THD* thd)
host was specified; there could have been a problem when replication host was specified; there could have been a problem when replication
started, which led to relay log's IO_CACHE to not be inited. started, which led to relay log's IO_CACHE to not be inited.
*/ */
flush_master_info(active_mi, 0); if (flush_master_info(active_mi, 0))
sql_print_error("Failed to flush master info file");
} }
mysql_free_result(master_status_res); mysql_free_result(master_status_res);
} }

View File

@ -2496,7 +2496,6 @@ bool sys_var_slave_skip_counter::update(THD *thd, set_var *var)
bool sys_var_sync_binlog_period::update(THD *thd, set_var *var) bool sys_var_sync_binlog_period::update(THD *thd, set_var *var)
{ {
pthread_mutex_t *lock_log= mysql_bin_log.get_log_lock();
sync_binlog_period= (ulong) var->save_result.ulonglong_value; sync_binlog_period= (ulong) var->save_result.ulonglong_value;
return 0; return 0;
} }

View File

@ -5798,3 +5798,5 @@ ER_CANT_WRITE_LOCK_LOG_TABLE
eng "You can't write-lock a log table. Only read access is possible." eng "You can't write-lock a log table. Only read access is possible."
ER_CANT_READ_LOCK_LOG_TABLE ER_CANT_READ_LOCK_LOG_TABLE
eng "You can't use usual read lock with log tables. Try READ LOCAL instead." eng "You can't use usual read lock with log tables. Try READ LOCAL instead."
ER_SP_WRONG_NAME 42000
eng "Incorrect routine name '%-.64s'"

View File

@ -1742,7 +1742,8 @@ static void write_ignored_events_info_to_relay_log(THD *thd, MASTER_INFO *mi)
" to the relay log, " " to the relay log, "
"SHOW SLAVE STATUS may be inaccurate"); "SHOW SLAVE STATUS may be inaccurate");
rli->relay_log.harvest_bytes_written(&rli->log_space_total); rli->relay_log.harvest_bytes_written(&rli->log_space_total);
flush_master_info(mi, 1); if (flush_master_info(mi, 1))
sql_print_error("Failed to flush master info file");
delete ev; delete ev;
} }
else else
@ -2233,7 +2234,7 @@ bool show_master_info(THD* thd, MASTER_INFO* mi)
pthread_mutex_unlock(&mi->rli.data_lock); pthread_mutex_unlock(&mi->rli.data_lock);
pthread_mutex_unlock(&mi->data_lock); pthread_mutex_unlock(&mi->data_lock);
if (my_net_write(&thd->net, (char*)thd->packet.ptr(), packet->length())) if (my_net_write(&thd->net, (char*)thd->packet.ptr(), packet->length()))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
@ -2241,8 +2242,13 @@ bool show_master_info(THD* thd, MASTER_INFO* mi)
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
} }
/*
bool flush_master_info(MASTER_INFO* mi, bool flush_relay_log_cache) RETURN
2 - flush relay log failed
1 - flush master info failed
0 - all ok
*/
int flush_master_info(MASTER_INFO* mi, bool flush_relay_log_cache)
{ {
IO_CACHE* file = &mi->file; IO_CACHE* file = &mi->file;
char lbuf[22]; char lbuf[22];
@ -2261,8 +2267,9 @@ bool flush_master_info(MASTER_INFO* mi, bool flush_relay_log_cache)
When we come to this place in code, relay log may or not be initialized; When we come to this place in code, relay log may or not be initialized;
the caller is responsible for setting 'flush_relay_log_cache' accordingly. the caller is responsible for setting 'flush_relay_log_cache' accordingly.
*/ */
if (flush_relay_log_cache) if (flush_relay_log_cache &&
flush_io_cache(mi->rli.relay_log.get_log_file()); flush_io_cache(mi->rli.relay_log.get_log_file()))
DBUG_RETURN(2);
/* /*
We flushed the relay log BEFORE the master.info file, because if we crash We flushed the relay log BEFORE the master.info file, because if we crash
@ -2274,13 +2281,13 @@ bool flush_master_info(MASTER_INFO* mi, bool flush_relay_log_cache)
*/ */
/* /*
In certain cases this code may create master.info files that seems In certain cases this code may create master.info files that seems
corrupted, because of extra lines filled with garbage in the end corrupted, because of extra lines filled with garbage in the end
file (this happens if new contents take less space than previous file (this happens if new contents take less space than previous
contents of file). But because of number of lines in the first line contents of file). But because of number of lines in the first line
of file we don't care about this garbage. of file we don't care about this garbage.
*/ */
my_b_seek(file, 0L); my_b_seek(file, 0L);
my_b_printf(file, "%u\n%s\n%s\n%s\n%s\n%s\n%d\n%d\n%d\n%s\n%s\n%s\n%s\n%s\n", my_b_printf(file, "%u\n%s\n%s\n%s\n%s\n%s\n%d\n%d\n%d\n%s\n%s\n%s\n%s\n%s\n",
LINES_IN_MASTER_INFO_WITH_SSL, LINES_IN_MASTER_INFO_WITH_SSL,
@ -2289,8 +2296,7 @@ bool flush_master_info(MASTER_INFO* mi, bool flush_relay_log_cache)
mi->password, mi->port, mi->connect_retry, mi->password, mi->port, mi->connect_retry,
(int)(mi->ssl), mi->ssl_ca, mi->ssl_capath, mi->ssl_cert, (int)(mi->ssl), mi->ssl_ca, mi->ssl_capath, mi->ssl_cert,
mi->ssl_cipher, mi->ssl_key); mi->ssl_cipher, mi->ssl_key);
flush_io_cache(file); DBUG_RETURN(-flush_io_cache(file));
DBUG_RETURN(0);
} }
@ -3355,7 +3361,11 @@ reconnect done to recover from failed read");
sql_print_error("Slave I/O thread could not queue event from master"); sql_print_error("Slave I/O thread could not queue event from master");
goto err; goto err;
} }
flush_master_info(mi, 1); /* sure that we can flush the relay log */ if (flush_master_info(mi, 1))
{
sql_print_error("Failed to flush master info file");
goto err;
}
/* /*
See if the relay logs take too much space. See if the relay logs take too much space.
We don't lock mi->rli.log_space_lock here; this dirty read saves time We don't lock mi->rli.log_space_lock here; this dirty read saves time

View File

@ -231,7 +231,7 @@ int queue_event(MASTER_INFO* mi,const char* buf,ulong event_len);
int init_slave(); int init_slave();
void init_slave_skip_errors(const char* arg); void init_slave_skip_errors(const char* arg);
bool flush_master_info(MASTER_INFO* mi, bool flush_relay_log_cache); int flush_master_info(MASTER_INFO* mi, bool flush_relay_log_cache);
bool flush_relay_log_info(RELAY_LOG_INFO* rli); bool flush_relay_log_info(RELAY_LOG_INFO* rli);
int register_slave_on_master(MYSQL* mysql); int register_slave_on_master(MYSQL* mysql);
int terminate_slave_threads(MASTER_INFO* mi, int thread_mask, int terminate_slave_threads(MASTER_INFO* mi, int thread_mask,

View File

@ -105,21 +105,27 @@ sp_get_item_value(Item *item, String *str)
case STRING_RESULT: case STRING_RESULT:
{ {
char buf_holder[STRING_BUFFER_USUAL_SIZE];
String buf(buf_holder, sizeof(buf_holder), &my_charset_latin1);
String *result= item->val_str(str); String *result= item->val_str(str);
if (!result) if (!result)
return NULL; return NULL;
buf.append('_'); {
buf.append(result->charset()->csname); char buf_holder[STRING_BUFFER_USUAL_SIZE];
buf.append('\''); String buf(buf_holder, sizeof(buf_holder), result->charset());
buf.append(*result);
buf.append('\'');
str->copy(buf);
return str; /* We must reset length of the buffer, because of String specificity. */
buf.length(0);
buf.append('_');
buf.append(result->charset()->csname);
buf.append('\'');
buf.append(*result);
buf.append('\'');
str->copy(buf);
return str;
}
} }
case ROW_RESULT: case ROW_RESULT:
@ -389,6 +395,23 @@ sp_name_current_db_new(THD *thd, LEX_STRING name)
return qname; return qname;
} }
/*
Check that the name 'ident' is ok. It's assumed to be an 'ident'
from the parser, so we only have to check length and trailing spaces.
The former is a standard requirement (and 'show status' assumes a
non-empty name), the latter is a mysql:ism as trailing spaces are
removed by get_field().
RETURN
TRUE - bad name
FALSE - name is ok
*/
bool
check_routine_name(LEX_STRING ident)
{
return (!ident.str || !ident.str[0] || ident.str[ident.length-1] == ' ');
}
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
@ -3083,9 +3106,16 @@ sp_instr_set_case_expr::exec_core(THD *thd, uint *nextp)
void void
sp_instr_set_case_expr::print(String *str) sp_instr_set_case_expr::print(String *str)
{ {
str->append(STRING_WITH_LEN("set_case_expr ")); const char CASE_EXPR_TAG[]= "set_case_expr ";
const int CASE_EXPR_TAG_LEN= sizeof(CASE_EXPR_TAG) - 1;
const int INT_STRING_MAX_LEN= 10;
/* We must call reserve(), because qs_append() doesn't care about memory. */
str->reserve(CASE_EXPR_TAG_LEN + INT_STRING_MAX_LEN + 2);
str->qs_append(CASE_EXPR_TAG, CASE_EXPR_TAG_LEN);
str->qs_append(m_case_expr_id); str->qs_append(m_case_expr_id);
str->append(' '); str->qs_append(' ');
m_case_expr->print(str); m_case_expr->print(str);
} }

View File

@ -103,6 +103,8 @@ public:
sp_name * sp_name *
sp_name_current_db_new(THD *thd, LEX_STRING name); sp_name_current_db_new(THD *thd, LEX_STRING name);
bool
check_routine_name(LEX_STRING name);
class sp_head :private Query_arena class sp_head :private Query_arena
{ {

View File

@ -142,7 +142,7 @@ struct MBR
bool inner_point(double x, double y) const bool inner_point(double x, double y) const
{ {
/* The following should be safe, even if we compare doubles */ /* The following should be safe, even if we compare doubles */
return (xmin<x) && (xmax>x) && (ymin<y) && (ymax>x); return (xmin<x) && (xmax>x) && (ymin<y) && (ymax>y);
} }
int overlaps(const MBR *mbr) int overlaps(const MBR *mbr)

View File

@ -951,7 +951,7 @@ bool acl_getroot_no_password(Security_context *sctx, char *user, char *host,
DBUG_PRINT("enter", ("Host: '%s', Ip: '%s', User: '%s', db: '%s'", DBUG_PRINT("enter", ("Host: '%s', Ip: '%s', User: '%s', db: '%s'",
(host ? host : "(NULL)"), (ip ? ip : "(NULL)"), (host ? host : "(NULL)"), (ip ? ip : "(NULL)"),
(user ? user : "(NULL)"), (db ? db : "(NULL)"))); user, (db ? db : "(NULL)")));
sctx->user= user; sctx->user= user;
sctx->host= host; sctx->host= host;
sctx->ip= ip; sctx->ip= ip;
@ -980,7 +980,7 @@ bool acl_getroot_no_password(Security_context *sctx, char *user, char *host,
for (i=0 ; i < acl_users.elements ; i++) for (i=0 ; i < acl_users.elements ; i++)
{ {
acl_user= dynamic_element(&acl_users,i,ACL_USER*); acl_user= dynamic_element(&acl_users,i,ACL_USER*);
if ((!acl_user->user && (!user || !user[0])) || if ((!acl_user->user && !user[0]) ||
(acl_user->user && strcmp(user, acl_user->user) == 0)) (acl_user->user && strcmp(user, acl_user->user) == 0))
{ {
if (compare_hostname(&acl_user->host, host, ip)) if (compare_hostname(&acl_user->host, host, ip))
@ -1001,7 +1001,7 @@ bool acl_getroot_no_password(Security_context *sctx, char *user, char *host,
{ {
if (compare_hostname(&acl_db->host, host, ip)) if (compare_hostname(&acl_db->host, host, ip))
{ {
if (!acl_db->db || (db && !strcmp(acl_db->db, db))) if (!acl_db->db || (db && !wild_compare(db, acl_db->db, 0)))
{ {
sctx->db_access= acl_db->access; sctx->db_access= acl_db->access;
break; break;
@ -4980,8 +4980,6 @@ static int handle_grant_struct(uint struct_no, bool drop,
} }
if (! user) if (! user)
user= ""; user= "";
if (! host)
host= "";
#ifdef EXTRA_DEBUG #ifdef EXTRA_DEBUG
DBUG_PRINT("loop",("scan struct: %u index: %u user: '%s' host: '%s'", DBUG_PRINT("loop",("scan struct: %u index: %u user: '%s' host: '%s'",
struct_no, idx, user, host)); struct_no, idx, user, host));

View File

@ -287,7 +287,7 @@ static bool write_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create)
} }
/* /*
Load database options file Load database options file
load_db_opt() load_db_opt()
@ -313,68 +313,72 @@ bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create)
bzero((char*) create,sizeof(*create)); bzero((char*) create,sizeof(*create));
create->default_table_charset= thd->variables.collation_server; create->default_table_charset= thd->variables.collation_server;
/* Check if options for this database are already in the hash */ /* Check if options for this database are already in the hash */
if (!get_dbopt(path, create)) if (!get_dbopt(path, create))
DBUG_RETURN(0); DBUG_RETURN(0);
/* Otherwise, load options from the .opt file */
if ((file=my_open(path, O_RDONLY | O_SHARE, MYF(0))) >= 0)
{
IO_CACHE cache;
init_io_cache(&cache, file, IO_SIZE, READ_CACHE, 0, 0, MYF(0));
while ((int) (nbytes= my_b_gets(&cache, (char*) buf, sizeof(buf))) > 0) /* Otherwise, load options from the .opt file */
if ((file=my_open(path, O_RDONLY | O_SHARE, MYF(0))) < 0)
goto err1;
IO_CACHE cache;
if (init_io_cache(&cache, file, IO_SIZE, READ_CACHE, 0, 0, MYF(0)))
goto err2;
while ((int) (nbytes= my_b_gets(&cache, (char*) buf, sizeof(buf))) > 0)
{
char *pos= buf+nbytes-1;
/* Remove end space and control characters */
while (pos > buf && !my_isgraph(&my_charset_latin1, pos[-1]))
pos--;
*pos=0;
if ((pos= strchr(buf, '=')))
{ {
char *pos= buf+nbytes-1; if (!strncmp(buf,"default-character-set", (pos-buf)))
/* Remove end space and control characters */
while (pos > buf && !my_isgraph(&my_charset_latin1, pos[-1]))
pos--;
*pos=0;
if ((pos= strchr(buf, '=')))
{ {
if (!strncmp(buf,"default-character-set", (pos-buf))) /*
{ Try character set name, and if it fails
/* try collation name, probably it's an old
Try character set name, and if it fails 4.1.0 db.opt file, which didn't have
try collation name, probably it's an old separate default-character-set and
4.1.0 db.opt file, which didn't have default-collation commands.
separate default-character-set and */
default-collation commands. if (!(create->default_table_charset=
*/ get_charset_by_csname(pos+1, MY_CS_PRIMARY, MYF(0))) &&
if (!(create->default_table_charset= !(create->default_table_charset=
get_charset_by_csname(pos+1, MY_CS_PRIMARY, MYF(0))) && get_charset_by_name(pos+1, MYF(0))))
!(create->default_table_charset= {
get_charset_by_name(pos+1, MYF(0)))) sql_print_error("Error while loading database options: '%s':",path);
{ sql_print_error(ER(ER_UNKNOWN_CHARACTER_SET),pos+1);
sql_print_error("Error while loading database options: '%s':",path); create->default_table_charset= default_charset_info;
sql_print_error(ER(ER_UNKNOWN_CHARACTER_SET),pos+1); }
create->default_table_charset= default_charset_info; }
} else if (!strncmp(buf,"default-collation", (pos-buf)))
} {
else if (!strncmp(buf,"default-collation", (pos-buf))) if (!(create->default_table_charset= get_charset_by_name(pos+1,
{ MYF(0))))
if (!(create->default_table_charset= get_charset_by_name(pos+1, {
MYF(0)))) sql_print_error("Error while loading database options: '%s':",path);
{ sql_print_error(ER(ER_UNKNOWN_COLLATION),pos+1);
sql_print_error("Error while loading database options: '%s':",path); create->default_table_charset= default_charset_info;
sql_print_error(ER(ER_UNKNOWN_COLLATION),pos+1); }
create->default_table_charset= default_charset_info;
}
}
} }
} }
end_io_cache(&cache);
my_close(file,MYF(0));
/*
Put the loaded value into the hash.
Note that another thread could've added the same
entry to the hash after we called get_dbopt(),
but it's not an error, as put_dbopt() takes this
possibility into account.
*/
error= put_dbopt(path, create);
} }
/*
Put the loaded value into the hash.
Note that another thread could've added the same
entry to the hash after we called get_dbopt(),
but it's not an error, as put_dbopt() takes this
possibility into account.
*/
error= put_dbopt(path, create);
end_io_cache(&cache);
err2:
my_close(file,MYF(0));
err1:
DBUG_RETURN(error); DBUG_RETURN(error);
} }

View File

@ -567,7 +567,7 @@ SQL_SELECT *prepare_simple_select(THD *thd, Item *cond,
SQL_SELECT *res= make_select(table, 0, 0, cond, 0, error); SQL_SELECT *res= make_select(table, 0, 0, cond, 0, error);
if (*error || (res && res->check_quick(thd, 0, HA_POS_ERROR)) || if (*error || (res && res->check_quick(thd, 0, HA_POS_ERROR)) ||
(res->quick && res->quick->reset())) (res && res->quick && res->quick->reset()))
{ {
delete res; delete res;
res=0; res=0;

View File

@ -686,7 +686,7 @@ static bool check_view_insertability(THD * thd, TABLE_LIST *view)
DBUG_ASSERT(view->table != 0 && view->field_translation != 0); DBUG_ASSERT(view->table != 0 && view->field_translation != 0);
bitmap_init(&used_fields, used_fields_buff, table->s->fields, 0); VOID(bitmap_init(&used_fields, used_fields_buff, table->s->fields, 0));
bitmap_clear_all(&used_fields); bitmap_clear_all(&used_fields);
view->contain_auto_increment= 0; view->contain_auto_increment= 0;

View File

@ -1615,6 +1615,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
statistic_increment(thd->status_var.com_other, &LOCK_status); statistic_increment(thd->status_var.com_other, &LOCK_status);
thd->enable_slow_log= opt_log_slow_admin_statements; thd->enable_slow_log= opt_log_slow_admin_statements;
db= thd->alloc(db_len + tbl_len + 2); db= thd->alloc(db_len + tbl_len + 2);
if (!db)
{
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
break;
}
tbl_name= strmake(db, packet + 1, db_len)+1; tbl_name= strmake(db, packet + 1, db_len)+1;
strmake(tbl_name, packet + db_len + 2, tbl_len); strmake(tbl_name, packet + db_len + 2, tbl_len);
mysql_table_dump(thd, db, tbl_name, -1); mysql_table_dump(thd, db, tbl_name, -1);
@ -1628,14 +1633,14 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
statistic_increment(thd->status_var.com_other, &LOCK_status); statistic_increment(thd->status_var.com_other, &LOCK_status);
char *user= (char*) packet; char *user= (char*) packet;
char *passwd= strend(user)+1; char *passwd= strend(user)+1;
/* /*
Old clients send null-terminated string ('\0' for empty string) for Old clients send null-terminated string ('\0' for empty string) for
password. New clients send the size (1 byte) + string (not null password. New clients send the size (1 byte) + string (not null
terminated, so also '\0' for empty string). terminated, so also '\0' for empty string).
*/ */
char db_buff[NAME_LEN+1]; // buffer to store db in utf8 char db_buff[NAME_LEN+1]; // buffer to store db in utf8
char *db= passwd; char *db= passwd;
uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ? uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ?
*passwd++ : strlen(passwd); *passwd++ : strlen(passwd);
db+= passwd_len + 1; db+= passwd_len + 1;
#ifndef EMBEDDED_LIBRARY #ifndef EMBEDDED_LIBRARY
@ -2414,23 +2419,26 @@ mysql_execute_command(THD *thd)
} }
} }
else else
#endif /* HAVE_REPLICATION */
/*
When option readonly is set deny operations which change non-temporary
tables. Except for the replication thread and the 'super' users.
*/
if (opt_readonly &&
!(thd->security_ctx->master_access & SUPER_ACL) &&
uc_update_queries[lex->sql_command] &&
!((lex->sql_command == SQLCOM_CREATE_TABLE) &&
(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE)) &&
((lex->sql_command != SQLCOM_UPDATE_MULTI) &&
some_non_temp_table_to_be_updated(thd, all_tables)))
{ {
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only"); #endif /* HAVE_REPLICATION */
DBUG_RETURN(-1); /*
} When option readonly is set deny operations which change non-temporary
tables. Except for the replication thread and the 'super' users.
*/
if (opt_readonly &&
!(thd->security_ctx->master_access & SUPER_ACL) &&
uc_update_queries[lex->sql_command] &&
!((lex->sql_command == SQLCOM_CREATE_TABLE) &&
(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE)) &&
((lex->sql_command != SQLCOM_UPDATE_MULTI) &&
some_non_temp_table_to_be_updated(thd, all_tables)))
{
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
DBUG_RETURN(-1);
}
#ifdef HAVE_REPLICATION
} /* endif unlikely slave */
#endif
if(lex->orig_sql_command == SQLCOM_END) if(lex->orig_sql_command == SQLCOM_END)
statistic_increment(thd->status_var.com_stat[lex->sql_command], statistic_increment(thd->status_var.com_stat[lex->sql_command],
&LOCK_status); &LOCK_status);
@ -3226,8 +3234,7 @@ end_with_restore_list:
else else
res= 0; res= 0;
if ((res= mysql_multi_update_prepare(thd))) res= mysql_multi_update_prepare(thd);
break;
#ifdef HAVE_REPLICATION #ifdef HAVE_REPLICATION
/* Check slave filtering rules */ /* Check slave filtering rules */
@ -3235,20 +3242,33 @@ end_with_restore_list:
{ {
if (all_tables_not_ok(thd, all_tables)) if (all_tables_not_ok(thd, all_tables))
{ {
if (res!= 0)
{
res= 0; /* don't care of prev failure */
thd->clear_error(); /* filters are of highest prior */
}
/* we warn the slave SQL thread */ /* we warn the slave SQL thread */
my_error(ER_SLAVE_IGNORED_TABLE, MYF(0)); my_error(ER_SLAVE_IGNORED_TABLE, MYF(0));
break; break;
} }
if (res)
break;
} }
else else
#endif /* HAVE_REPLICATION */
if (opt_readonly &&
!(thd->security_ctx->master_access & SUPER_ACL) &&
some_non_temp_table_to_be_updated(thd, all_tables))
{ {
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only"); #endif /* HAVE_REPLICATION */
break; if (res)
} break;
if (opt_readonly &&
!(thd->security_ctx->master_access & SUPER_ACL) &&
some_non_temp_table_to_be_updated(thd, all_tables))
{
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
break;
}
#ifdef HAVE_REPLICATION
} /* unlikely */
#endif
res= mysql_multi_update(thd, all_tables, res= mysql_multi_update(thd, all_tables,
&select_lex->item_list, &select_lex->item_list,
@ -6631,6 +6651,7 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
#ifdef HAVE_REPLICATION #ifdef HAVE_REPLICATION
if (options & REFRESH_MASTER) if (options & REFRESH_MASTER)
{ {
DBUG_ASSERT(thd);
tmp_write_to_binlog= 0; tmp_write_to_binlog= 0;
if (reset_master(thd)) if (reset_master(thd))
{ {

View File

@ -2120,6 +2120,8 @@ void reinit_stmt_before_use(THD *thd, LEX *lex)
were closed in the end of previous prepare or execute call. were closed in the end of previous prepare or execute call.
*/ */
tables->table= 0; tables->table= 0;
/* Reset is_schema_table_processed value(needed for I_S tables */
tables->is_schema_table_processed= FALSE;
if (tables->prep_on_expr) if (tables->prep_on_expr)
{ {

View File

@ -1201,7 +1201,12 @@ bool change_master(THD* thd, MASTER_INFO* mi)
Relay log's IO_CACHE may not be inited, if rli->inited==0 (server was never Relay log's IO_CACHE may not be inited, if rli->inited==0 (server was never
a slave before). a slave before).
*/ */
flush_master_info(mi, 0); if (flush_master_info(mi, 0))
{
my_error(ER_RELAY_LOG_INIT, MYF(0), "Failed to flush master info file");
unlock_slave_threads(mi);
DBUG_RETURN(TRUE);
}
if (need_relay_log_purge) if (need_relay_log_purge)
{ {
relay_log_purge= 1; relay_log_purge= 1;
@ -1311,14 +1316,15 @@ bool mysql_show_binlog_events(THD* thd)
bool ret = TRUE; bool ret = TRUE;
IO_CACHE log; IO_CACHE log;
File file = -1; File file = -1;
Format_description_log_event *description_event= new
Format_description_log_event(3); /* MySQL 4.0 by default */
Log_event::init_show_field_list(&field_list); Log_event::init_show_field_list(&field_list);
if (protocol->send_fields(&field_list, if (protocol->send_fields(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
Format_description_log_event *description_event= new
Format_description_log_event(3); /* MySQL 4.0 by default */
/* /*
Wait for handlers to insert any pending information Wait for handlers to insert any pending information
into the binlog. For e.g. ndb which updates the binlog asynchronously into the binlog. For e.g. ndb which updates the binlog asynchronously

View File

@ -9117,7 +9117,7 @@ TABLE *create_virtual_tmp_table(THD *thd, List<create_field> &field_list)
field++; field++;
} }
*field= NULL; /* mark the end of the list */ *field= NULL; /* mark the end of the list */
share->blob_field[blob_count]= 0; /* mark the end of the list */ share->blob_field[blob_count]= 0; /* mark the end of the list */
share->blob_fields= blob_count; share->blob_fields= blob_count;
@ -11659,6 +11659,12 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
goto err; goto err;
} }
} }
/* Fill schema tables with data before filesort if it's necessary */
if ((join->select_lex->options & OPTION_SCHEMA_TABLE) &&
get_schema_tables_result(join))
goto err;
if (table->s->tmp_table) if (table->s->tmp_table)
table->file->info(HA_STATUS_VARIABLE); // Get record count table->file->info(HA_STATUS_VARIABLE); // Get record count
table->sort.found_records=filesort(thd, table,sortorder, length, table->sort.found_records=filesort(thd, table,sortorder, length,

View File

@ -781,7 +781,7 @@ append_identifier(THD *thd, String *packet, const char *name, uint length)
it's a keyword it's a keyword
*/ */
packet->reserve(length*2 + 2); VOID(packet->reserve(length*2 + 2));
quote_char= (char) q; quote_char= (char) q;
packet->append(&quote_char, 1, system_charset_info); packet->append(&quote_char, 1, system_charset_info);
@ -1097,13 +1097,13 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
if (key_part->field) if (key_part->field)
append_identifier(thd,packet,key_part->field->field_name, append_identifier(thd,packet,key_part->field->field_name,
strlen(key_part->field->field_name)); strlen(key_part->field->field_name));
if (!key_part->field || if (key_part->field &&
(key_part->length != (key_part->length !=
table->field[key_part->fieldnr-1]->key_length() && table->field[key_part->fieldnr-1]->key_length() &&
!(key_info->flags & HA_FULLTEXT))) !(key_info->flags & HA_FULLTEXT)))
{ {
buff[0] = '('; buff[0] = '(';
char* end=int10_to_str((long) key_part->length / char* end=int10_to_str((long) key_part->length /
key_part->field->charset()->mbmaxlen, key_part->field->charset()->mbmaxlen,
buff + 1,10); buff + 1,10);
*end++ = ')'; *end++ = ')';
@ -1856,7 +1856,8 @@ LEX_STRING *make_lex_string(THD *thd, LEX_STRING *lex_str,
{ {
MEM_ROOT *mem= thd->mem_root; MEM_ROOT *mem= thd->mem_root;
if (allocate_lex_string) if (allocate_lex_string)
lex_str= (LEX_STRING *)thd->alloc(sizeof(LEX_STRING)); if (!(lex_str= (LEX_STRING *)thd->alloc(sizeof(LEX_STRING))))
return 0;
lex_str->str= strmake_root(mem, str, length); lex_str->str= strmake_root(mem, str, length);
lex_str->length= length; lex_str->length= length;
return lex_str; return lex_str;
@ -3115,7 +3116,7 @@ static int get_schema_stat_record(THD *thd, struct st_table_list *tables,
/* /*
I.e. we are in SELECT FROM INFORMATION_SCHEMA.STATISTICS I.e. we are in SELECT FROM INFORMATION_SCHEMA.STATISTICS
rather than in SHOW KEYS rather than in SHOW KEYS
*/ */
if (!tables->view) if (!tables->view)
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
thd->net.last_errno, thd->net.last_error); thd->net.last_errno, thd->net.last_error);
@ -3128,7 +3129,7 @@ static int get_schema_stat_record(THD *thd, struct st_table_list *tables,
{ {
TABLE *show_table= tables->table; TABLE *show_table= tables->table;
KEY *key_info=show_table->key_info; KEY *key_info=show_table->key_info;
show_table->file->info(HA_STATUS_VARIABLE | show_table->file->info(HA_STATUS_VARIABLE |
HA_STATUS_NO_LOCK | HA_STATUS_NO_LOCK |
HA_STATUS_TIME); HA_STATUS_TIME);
for (uint i=0 ; i < show_table->s->keys ; i++,key_info++) for (uint i=0 ; i < show_table->s->keys ; i++,key_info++)
@ -3140,7 +3141,7 @@ static int get_schema_stat_record(THD *thd, struct st_table_list *tables,
restore_record(table, s->default_values); restore_record(table, s->default_values);
table->field[1]->store(base_name, strlen(base_name), cs); table->field[1]->store(base_name, strlen(base_name), cs);
table->field[2]->store(file_name, strlen(file_name), cs); table->field[2]->store(file_name, strlen(file_name), cs);
table->field[3]->store((longlong) ((key_info->flags & table->field[3]->store((longlong) ((key_info->flags &
HA_NOSAME) ? 0 : 1), TRUE); HA_NOSAME) ? 0 : 1), TRUE);
table->field[4]->store(base_name, strlen(base_name), cs); table->field[4]->store(base_name, strlen(base_name), cs);
table->field[5]->store(key_info->name, strlen(key_info->name), cs); table->field[5]->store(key_info->name, strlen(key_info->name), cs);
@ -3163,12 +3164,12 @@ static int get_schema_stat_record(THD *thd, struct st_table_list *tables,
table->field[9]->store((longlong) records, TRUE); table->field[9]->store((longlong) records, TRUE);
table->field[9]->set_notnull(); table->field[9]->set_notnull();
} }
if (!(key_info->flags & HA_FULLTEXT) && if (!(key_info->flags & HA_FULLTEXT) &&
(!key_part->field || (key_part->field &&
key_part->length != key_part->length !=
show_table->field[key_part->fieldnr-1]->key_length())) show_table->field[key_part->fieldnr-1]->key_length()))
{ {
table->field[10]->store((longlong) key_part->length / table->field[10]->store((longlong) key_part->length /
key_part->field->charset()->mbmaxlen); key_part->field->charset()->mbmaxlen);
table->field[10]->set_notnull(); table->field[10]->set_notnull();
} }
@ -4549,7 +4550,16 @@ bool get_schema_tables_result(JOIN *join)
TABLE_LIST *table_list= tab->table->pos_in_table_list; TABLE_LIST *table_list= tab->table->pos_in_table_list;
if (table_list->schema_table && thd->fill_derived_tables()) if (table_list->schema_table && thd->fill_derived_tables())
{ {
if (&lex->unit != lex->current_select->master_unit()) // is subselect bool is_subselect= (&lex->unit != lex->current_select->master_unit());
/*
The schema table is already processed and
the statement is not a subselect.
So we don't need to handle this table again.
*/
if (table_list->is_schema_table_processed && !is_subselect)
continue;
if (is_subselect) // is subselect
{ {
table_list->table->file->extra(HA_EXTRA_RESET_STATE); table_list->table->file->extra(HA_EXTRA_RESET_STATE);
table_list->table->file->delete_all_rows(); table_list->table->file->delete_all_rows();
@ -4562,6 +4572,7 @@ bool get_schema_tables_result(JOIN *join)
if (table_list->schema_table->fill_table(thd, table_list, if (table_list->schema_table->fill_table(thd, table_list,
tab->select_cond)) tab->select_cond))
result= 1; result= 1;
table_list->is_schema_table_processed= TRUE;
} }
} }
thd->no_warnings_for_error= 0; thd->no_warnings_for_error= 0;

View File

@ -450,7 +450,7 @@ void mysql_print_status()
calc_sum_of_all_status(&tmp); calc_sum_of_all_status(&tmp);
printf("\nStatus information:\n\n"); printf("\nStatus information:\n\n");
my_getwd(current_dir, sizeof(current_dir),MYF(0)); VOID(my_getwd(current_dir, sizeof(current_dir),MYF(0)));
printf("Current dir: %s\n", current_dir); printf("Current dir: %s\n", current_dir);
printf("Running threads: %d Stack size: %ld\n", thread_count, printf("Running threads: %d Stack size: %ld\n", thread_count,
(long) thread_stack); (long) thread_stack);

View File

@ -1642,11 +1642,26 @@ clear_privileges:
sp_name: sp_name:
ident '.' ident ident '.' ident
{ {
if (!$1.str || check_db_name($1.str))
{
my_error(ER_WRONG_DB_NAME, MYF(0), $1.str);
YYABORT;
}
if (check_routine_name($3))
{
my_error(ER_SP_WRONG_NAME, MYF(0), $3.str);
YYABORT;
}
$$= new sp_name($1, $3); $$= new sp_name($1, $3);
$$->init_qname(YYTHD); $$->init_qname(YYTHD);
} }
| ident | ident
{ {
if (check_routine_name($1))
{
my_error(ER_SP_WRONG_NAME, MYF(0), $1.str);
YYABORT;
}
$$= sp_name_current_db_new(YYTHD, $1); $$= sp_name_current_db_new(YYTHD, $1);
} }
; ;

View File

@ -1640,7 +1640,10 @@ ulong get_form_pos(File file, uchar *head, TYPELIB *save_names)
ret_value=uint4korr(pos); ret_value=uint4korr(pos);
} }
if (! save_names) if (! save_names)
my_free((gptr) buf,MYF(0)); {
if (names)
my_free((gptr) buf,MYF(0));
}
else if (!names) else if (!names)
bzero((char*) save_names,sizeof(save_names)); bzero((char*) save_names,sizeof(save_names));
else else

View File

@ -560,6 +560,7 @@ typedef struct st_table_list
st_select_lex_unit *derived; /* SELECT_LEX_UNIT of derived table */ st_select_lex_unit *derived; /* SELECT_LEX_UNIT of derived table */
ST_SCHEMA_TABLE *schema_table; /* Information_schema table */ ST_SCHEMA_TABLE *schema_table; /* Information_schema table */
st_select_lex *schema_select_lex; st_select_lex *schema_select_lex;
bool is_schema_table_processed;
/* /*
True when the view field translation table is used to convert True when the view field translation table is used to convert
schema table fields for backwards compatibility with SHOW command. schema table fields for backwards compatibility with SHOW command.

View File

@ -38,8 +38,8 @@
int unique_write_to_file(gptr key, element_count count, Unique *unique) int unique_write_to_file(gptr key, element_count count, Unique *unique)
{ {
/* /*
Use unique->size (size of element stored in the tree) and not Use unique->size (size of element stored in the tree) and not
unique->tree.size_of_element. The latter is different from unique->size unique->tree.size_of_element. The latter is different from unique->size
when tree implementation chooses to store pointer to key in TREE_ELEMENT when tree implementation chooses to store pointer to key in TREE_ELEMENT
(instead of storing the element itself there) (instead of storing the element itself there)
*/ */
@ -63,27 +63,27 @@ Unique::Unique(qsort_cmp2 comp_func, void * comp_func_fixed_arg,
comp_func_fixed_arg); comp_func_fixed_arg);
/* If the following fail's the next add will also fail */ /* If the following fail's the next add will also fail */
my_init_dynamic_array(&file_ptrs, sizeof(BUFFPEK), 16, 16); my_init_dynamic_array(&file_ptrs, sizeof(BUFFPEK), 16, 16);
/* /*
If you change the following, change it in get_max_elements function, too. If you change the following, change it in get_max_elements function, too.
*/ */
max_elements= max_in_memory_size / ALIGN_SIZE(sizeof(TREE_ELEMENT)+size); max_elements= max_in_memory_size / ALIGN_SIZE(sizeof(TREE_ELEMENT)+size);
open_cached_file(&file, mysql_tmpdir,TEMP_PREFIX, DISK_BUFFER_SIZE, VOID(open_cached_file(&file, mysql_tmpdir,TEMP_PREFIX, DISK_BUFFER_SIZE,
MYF(MY_WME)); MYF(MY_WME)));
} }
/* /*
Calculate log2(n!) Calculate log2(n!)
NOTES NOTES
Stirling's approximate formula is used: Stirling's approximate formula is used:
n! ~= sqrt(2*M_PI*n) * (n/M_E)^n n! ~= sqrt(2*M_PI*n) * (n/M_E)^n
Derivation of formula used for calculations is as follows: Derivation of formula used for calculations is as follows:
log2(n!) = log(n!)/log(2) = log(sqrt(2*M_PI*n)*(n/M_E)^n) / log(2) = log2(n!) = log(n!)/log(2) = log(sqrt(2*M_PI*n)*(n/M_E)^n) / log(2) =
= (log(2*M_PI*n)/2 + n*log(n/M_E)) / log(2). = (log(2*M_PI*n)/2 + n*log(n/M_E)) / log(2).
*/ */
@ -94,7 +94,7 @@ inline double log2_n_fact(double x)
/* /*
Calculate cost of merge_buffers function call for given sequence of Calculate cost of merge_buffers function call for given sequence of
input stream lengths and store the number of rows in result stream in *last. input stream lengths and store the number of rows in result stream in *last.
SYNOPSIS SYNOPSIS
@ -103,21 +103,21 @@ inline double log2_n_fact(double x)
elem_size Size of element stored in buffer elem_size Size of element stored in buffer
first Pointer to first merged element size first Pointer to first merged element size
last Pointer to last merged element size last Pointer to last merged element size
RETURN RETURN
Cost of merge_buffers operation in disk seeks. Cost of merge_buffers operation in disk seeks.
NOTES NOTES
It is assumed that no rows are eliminated during merge. It is assumed that no rows are eliminated during merge.
The cost is calculated as The cost is calculated as
cost(read_and_write) + cost(merge_comparisons). cost(read_and_write) + cost(merge_comparisons).
All bytes in the sequences is read and written back during merge so cost All bytes in the sequences is read and written back during merge so cost
of disk io is 2*elem_size*total_buf_elems/IO_SIZE (2 is for read + write) of disk io is 2*elem_size*total_buf_elems/IO_SIZE (2 is for read + write)
For comparisons cost calculations we assume that all merged sequences have For comparisons cost calculations we assume that all merged sequences have
the same length, so each of total_buf_size elements will be added to a sort the same length, so each of total_buf_size elements will be added to a sort
heap with (n_buffers-1) elements. This gives the comparison cost: heap with (n_buffers-1) elements. This gives the comparison cost:
total_buf_elems* log2(n_buffers) / TIME_FOR_COMPARE_ROWID; total_buf_elems* log2(n_buffers) / TIME_FOR_COMPARE_ROWID;
@ -125,16 +125,16 @@ inline double log2_n_fact(double x)
static double get_merge_buffers_cost(uint *buff_elems, uint elem_size, static double get_merge_buffers_cost(uint *buff_elems, uint elem_size,
uint *first, uint *last) uint *first, uint *last)
{ {
uint total_buf_elems= 0; uint total_buf_elems= 0;
for (uint *pbuf= first; pbuf <= last; pbuf++) for (uint *pbuf= first; pbuf <= last; pbuf++)
total_buf_elems+= *pbuf; total_buf_elems+= *pbuf;
*last= total_buf_elems; *last= total_buf_elems;
int n_buffers= last - first + 1; int n_buffers= last - first + 1;
/* Using log2(n)=log(n)/log(2) formula */ /* Using log2(n)=log(n)/log(2) formula */
return 2*((double)total_buf_elems*elem_size) / IO_SIZE + return 2*((double)total_buf_elems*elem_size) / IO_SIZE +
total_buf_elems*log((double) n_buffers) / (TIME_FOR_COMPARE_ROWID * M_LN2); total_buf_elems*log((double) n_buffers) / (TIME_FOR_COMPARE_ROWID * M_LN2);
} }
@ -142,13 +142,13 @@ static double get_merge_buffers_cost(uint *buff_elems, uint elem_size,
/* /*
Calculate cost of merging buffers into one in Unique::get, i.e. calculate Calculate cost of merging buffers into one in Unique::get, i.e. calculate
how long (in terms of disk seeks) the two calls how long (in terms of disk seeks) the two calls
merge_many_buffs(...); merge_many_buffs(...);
merge_buffers(...); merge_buffers(...);
will take. will take.
SYNOPSIS SYNOPSIS
get_merge_many_buffs_cost() get_merge_many_buffs_cost()
buffer buffer space for temporary data, at least buffer buffer space for temporary data, at least
Unique::get_cost_calc_buff_size bytes Unique::get_cost_calc_buff_size bytes
maxbuffer # of full buffers maxbuffer # of full buffers
max_n_elems # of elements in first maxbuffer buffers max_n_elems # of elements in first maxbuffer buffers
@ -156,12 +156,12 @@ static double get_merge_buffers_cost(uint *buff_elems, uint elem_size,
elem_size size of buffer element elem_size size of buffer element
NOTES NOTES
maxbuffer+1 buffers are merged, where first maxbuffer buffers contain maxbuffer+1 buffers are merged, where first maxbuffer buffers contain
max_n_elems elements each and last buffer contains last_n_elems elements. max_n_elems elements each and last buffer contains last_n_elems elements.
The current implementation does a dumb simulation of merge_many_buffs The current implementation does a dumb simulation of merge_many_buffs
function actions. function actions.
RETURN RETURN
Cost of merge in disk seeks. Cost of merge in disk seeks.
*/ */
@ -173,17 +173,17 @@ static double get_merge_many_buffs_cost(uint *buffer,
register int i; register int i;
double total_cost= 0.0; double total_cost= 0.0;
uint *buff_elems= buffer; /* #s of elements in each of merged sequences */ uint *buff_elems= buffer; /* #s of elements in each of merged sequences */
/* /*
Set initial state: first maxbuffer sequences contain max_n_elems elements Set initial state: first maxbuffer sequences contain max_n_elems elements
each, last sequence contains last_n_elems elements. each, last sequence contains last_n_elems elements.
*/ */
for (i = 0; i < (int)maxbuffer; i++) for (i = 0; i < (int)maxbuffer; i++)
buff_elems[i]= max_n_elems; buff_elems[i]= max_n_elems;
buff_elems[maxbuffer]= last_n_elems; buff_elems[maxbuffer]= last_n_elems;
/* /*
Do it exactly as merge_many_buff function does, calling Do it exactly as merge_many_buff function does, calling
get_merge_buffers_cost to get cost of merge_buffers. get_merge_buffers_cost to get cost of merge_buffers.
*/ */
if (maxbuffer >= MERGEBUFF2) if (maxbuffer >= MERGEBUFF2)
@ -194,17 +194,17 @@ static double get_merge_many_buffs_cost(uint *buffer,
for (i = 0; i <= (int) maxbuffer - MERGEBUFF*3/2; i += MERGEBUFF) for (i = 0; i <= (int) maxbuffer - MERGEBUFF*3/2; i += MERGEBUFF)
{ {
total_cost+=get_merge_buffers_cost(buff_elems, elem_size, total_cost+=get_merge_buffers_cost(buff_elems, elem_size,
buff_elems + i, buff_elems + i,
buff_elems + i + MERGEBUFF-1); buff_elems + i + MERGEBUFF-1);
lastbuff++; lastbuff++;
} }
total_cost+=get_merge_buffers_cost(buff_elems, elem_size, total_cost+=get_merge_buffers_cost(buff_elems, elem_size,
buff_elems + i, buff_elems + i,
buff_elems + maxbuffer); buff_elems + maxbuffer);
maxbuffer= lastbuff; maxbuffer= lastbuff;
} }
} }
/* Simulate final merge_buff call. */ /* Simulate final merge_buff call. */
total_cost += get_merge_buffers_cost(buff_elems, elem_size, total_cost += get_merge_buffers_cost(buff_elems, elem_size,
buff_elems, buff_elems + maxbuffer); buff_elems, buff_elems + maxbuffer);
@ -213,7 +213,7 @@ static double get_merge_many_buffs_cost(uint *buffer,
/* /*
Calculate cost of using Unique for processing nkeys elements of size Calculate cost of using Unique for processing nkeys elements of size
key_size using max_in_memory_size memory. key_size using max_in_memory_size memory.
SYNOPSIS SYNOPSIS
@ -223,12 +223,12 @@ static double get_merge_many_buffs_cost(uint *buffer,
nkeys #of elements in Unique nkeys #of elements in Unique
key_size size of each elements in bytes key_size size of each elements in bytes
max_in_memory_size amount of memory Unique will be allowed to use max_in_memory_size amount of memory Unique will be allowed to use
RETURN RETURN
Cost in disk seeks. Cost in disk seeks.
NOTES NOTES
cost(using_unqiue) = cost(using_unqiue) =
cost(create_trees) + (see #1) cost(create_trees) + (see #1)
cost(merge) + (see #2) cost(merge) + (see #2)
cost(read_result) (see #3) cost(read_result) (see #3)
@ -237,42 +237,42 @@ static double get_merge_many_buffs_cost(uint *buffer,
For each Unique::put operation there will be 2*log2(n+1) elements For each Unique::put operation there will be 2*log2(n+1) elements
comparisons, where n runs from 1 tree_size (we assume that all added comparisons, where n runs from 1 tree_size (we assume that all added
elements are different). Together this gives: elements are different). Together this gives:
n_compares = 2*(log2(2) + log2(3) + ... + log2(N+1)) = 2*log2((N+1)!) n_compares = 2*(log2(2) + log2(3) + ... + log2(N+1)) = 2*log2((N+1)!)
then cost(tree_creation) = n_compares*ROWID_COMPARE_COST; then cost(tree_creation) = n_compares*ROWID_COMPARE_COST;
Total cost of creating trees: Total cost of creating trees:
(n_trees - 1)*max_size_tree_cost + non_max_size_tree_cost. (n_trees - 1)*max_size_tree_cost + non_max_size_tree_cost.
Approximate value of log2(N!) is calculated by log2_n_fact function. Approximate value of log2(N!) is calculated by log2_n_fact function.
2. Cost of merging. 2. Cost of merging.
If only one tree is created by Unique no merging will be necessary. If only one tree is created by Unique no merging will be necessary.
Otherwise, we model execution of merge_many_buff function and count Otherwise, we model execution of merge_many_buff function and count
#of merges. (The reason behind this is that number of buffers is small, #of merges. (The reason behind this is that number of buffers is small,
while size of buffers is big and we don't want to loose precision with while size of buffers is big and we don't want to loose precision with
O(x)-style formula) O(x)-style formula)
3. If only one tree is created by Unique no disk io will happen. 3. If only one tree is created by Unique no disk io will happen.
Otherwise, ceil(key_len*n_keys) disk seeks are necessary. We assume Otherwise, ceil(key_len*n_keys) disk seeks are necessary. We assume
these will be random seeks. these will be random seeks.
*/ */
double Unique::get_use_cost(uint *buffer, uint nkeys, uint key_size, double Unique::get_use_cost(uint *buffer, uint nkeys, uint key_size,
ulong max_in_memory_size) ulong max_in_memory_size)
{ {
ulong max_elements_in_tree; ulong max_elements_in_tree;
ulong last_tree_elems; ulong last_tree_elems;
int n_full_trees; /* number of trees in unique - 1 */ int n_full_trees; /* number of trees in unique - 1 */
double result; double result;
max_elements_in_tree= max_elements_in_tree=
max_in_memory_size / ALIGN_SIZE(sizeof(TREE_ELEMENT)+key_size); max_in_memory_size / ALIGN_SIZE(sizeof(TREE_ELEMENT)+key_size);
n_full_trees= nkeys / max_elements_in_tree; n_full_trees= nkeys / max_elements_in_tree;
last_tree_elems= nkeys % max_elements_in_tree; last_tree_elems= nkeys % max_elements_in_tree;
/* Calculate cost of creating trees */ /* Calculate cost of creating trees */
result= 2*log2_n_fact(last_tree_elems + 1.0); result= 2*log2_n_fact(last_tree_elems + 1.0);
if (n_full_trees) if (n_full_trees)
@ -285,13 +285,13 @@ double Unique::get_use_cost(uint *buffer, uint nkeys, uint key_size,
if (!n_full_trees) if (!n_full_trees)
return result; return result;
/* /*
There is more then one tree and merging is necessary. There is more then one tree and merging is necessary.
First, add cost of writing all trees to disk, assuming that all disk First, add cost of writing all trees to disk, assuming that all disk
writes are sequential. writes are sequential.
*/ */
result += DISK_SEEK_BASE_COST * n_full_trees * result += DISK_SEEK_BASE_COST * n_full_trees *
ceil(((double) key_size)*max_elements_in_tree / IO_SIZE); ceil(((double) key_size)*max_elements_in_tree / IO_SIZE);
result += DISK_SEEK_BASE_COST * ceil(((double) key_size)*last_tree_elems / IO_SIZE); result += DISK_SEEK_BASE_COST * ceil(((double) key_size)*last_tree_elems / IO_SIZE);
@ -303,8 +303,8 @@ double Unique::get_use_cost(uint *buffer, uint nkeys, uint key_size,
return merge_cost; return merge_cost;
result += merge_cost; result += merge_cost;
/* /*
Add cost of reading the resulting sequence, assuming there were no Add cost of reading the resulting sequence, assuming there were no
duplicate elements. duplicate elements.
*/ */
result += ceil((double)key_size*nkeys/IO_SIZE); result += ceil((double)key_size*nkeys/IO_SIZE);
@ -320,7 +320,7 @@ Unique::~Unique()
} }
/* Write tree to disk; clear tree */ /* Write tree to disk; clear tree */
bool Unique::flush() bool Unique::flush()
{ {
BUFFPEK file_ptr; BUFFPEK file_ptr;
@ -359,7 +359,7 @@ Unique::reset()
} }
elements= 0; elements= 0;
} }
/* /*
The comparison function, passed to queue_init() in merge_walk() must The comparison function, passed to queue_init() in merge_walk() must
use comparison function of Uniques::tree, but compare members of struct use comparison function of Uniques::tree, but compare members of struct
@ -386,7 +386,7 @@ C_MODE_END
/* /*
DESCRIPTION DESCRIPTION
Function is very similar to merge_buffers, but instead of writing sorted Function is very similar to merge_buffers, but instead of writing sorted
unique keys to the output file, it invokes walk_action for each key. unique keys to the output file, it invokes walk_action for each key.
This saves I/O if you need to pass through all unique keys only once. This saves I/O if you need to pass through all unique keys only once.
SYNOPSIS SYNOPSIS
@ -601,7 +601,7 @@ bool Unique::get(TABLE *table)
bool error=1; bool error=1;
/* Open cached file if it isn't open */ /* Open cached file if it isn't open */
outfile=table->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE), outfile=table->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE),
MYF(MY_ZEROFILL)); MYF(MY_ZEROFILL));
if (!outfile || ! my_b_inited(outfile) && if (!outfile || ! my_b_inited(outfile) &&
@ -618,7 +618,7 @@ bool Unique::get(TABLE *table)
sort_param.keys= max_in_memory_size / sort_param.sort_length; sort_param.keys= max_in_memory_size / sort_param.sort_length;
sort_param.not_killable=1; sort_param.not_killable=1;
if (!(sort_buffer=(uchar*) my_malloc((sort_param.keys+1) * if (!(sort_buffer=(uchar*) my_malloc((sort_param.keys+1) *
sort_param.sort_length, sort_param.sort_length,
MYF(0)))) MYF(0))))
return 1; return 1;
@ -633,7 +633,7 @@ bool Unique::get(TABLE *table)
goto err; goto err;
if (merge_buffers(&sort_param, &file, outfile, sort_buffer, file_ptr, if (merge_buffers(&sort_param, &file, outfile, sort_buffer, file_ptr,
file_ptr, file_ptr+maxbuffer,0)) file_ptr, file_ptr+maxbuffer,0))
goto err; goto err;
error=0; error=0;
err: err:
x_free((gptr) sort_buffer); x_free((gptr) sort_buffer);

View File

@ -174,6 +174,10 @@ int _mi_ft_cmp(MI_INFO *info, uint keynr, const byte *rec1, const byte *rec2)
FT_SEG_ITERATOR ftsi1, ftsi2; FT_SEG_ITERATOR ftsi1, ftsi2;
CHARSET_INFO *cs=info->s->keyinfo[keynr].seg->charset; CHARSET_INFO *cs=info->s->keyinfo[keynr].seg->charset;
DBUG_ENTER("_mi_ft_cmp"); DBUG_ENTER("_mi_ft_cmp");
#ifndef MYSQL_HAS_TRUE_CTYPE_IMPLEMENTATION
if (cs->mbmaxlen > 1)
DBUG_RETURN(THOSE_TWO_DAMN_KEYS_ARE_REALLY_DIFFERENT);
#endif
_mi_ft_segiterator_init(info, keynr, rec1, &ftsi1); _mi_ft_segiterator_init(info, keynr, rec1, &ftsi1);
_mi_ft_segiterator_init(info, keynr, rec2, &ftsi2); _mi_ft_segiterator_init(info, keynr, rec2, &ftsi2);

View File

@ -276,7 +276,8 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
if (subkeys == -1) if (subkeys == -1)
{ {
/* the last entry in sub-tree */ /* the last entry in sub-tree */
_mi_dispose(info, keyinfo, root,DFLT_INIT_HITS); if (_mi_dispose(info, keyinfo, root,DFLT_INIT_HITS))
DBUG_RETURN(-1);
/* fall through to normal delete */ /* fall through to normal delete */
} }
else else

View File

@ -1159,7 +1159,7 @@ static int compare_huff_elements(void *not_used __attribute__((unused)),
static void check_counts(HUFF_COUNTS *huff_counts, uint trees, static void check_counts(HUFF_COUNTS *huff_counts, uint trees,
my_off_t records) my_off_t records)
{ {
uint space_fields,fill_zero_fields,field_count[(int) FIELD_VARCHAR+1]; uint space_fields,fill_zero_fields,field_count[(int) FIELD_enum_val_count];
my_off_t old_length,new_length,length; my_off_t old_length,new_length,length;
DBUG_ENTER("check_counts"); DBUG_ENTER("check_counts");

View File

@ -376,7 +376,10 @@ pthread_handler_t thr_find_all_keys(void *arg)
{ {
if (my_init_dynamic_array(&info->buffpek, sizeof(BUFFPEK), if (my_init_dynamic_array(&info->buffpek, sizeof(BUFFPEK),
maxbuffer, maxbuffer/2)) maxbuffer, maxbuffer/2))
{
my_free((gptr) sort_keys,MYF(0)); my_free((gptr) sort_keys,MYF(0));
sort_keys= (uchar **) NULL; /* for err: label */
}
else else
break; break;
} }

View File

@ -125,6 +125,18 @@ public:
*/ */
void setErrorCode(int code); void setErrorCode(int code);
/**
* Returns the error string.
*/
char* getErrorStr();
/**
* Sets the error string.
*
* @param str the error string.
*/
void setErrorStr(char* str);
/** /**
* Parse logstring parameters * Parse logstring parameters
* *
@ -195,6 +207,7 @@ private:
const char* m_pDateTimeFormat; const char* m_pDateTimeFormat;
int m_errorCode; int m_errorCode;
char* m_errorStr;
// for handling repeated messages // for handling repeated messages
unsigned m_count_repeated_messages; unsigned m_count_repeated_messages;

View File

@ -178,8 +178,11 @@ public:
* Add a new handler * Add a new handler
* *
* @param logstring string describing the handler to add * @param logstring string describing the handler to add
* @param err OS errno in event of error
* @param len max length of errStr buffer
* @param errStr logger error string in event of error
*/ */
bool addHandler(const BaseString &logstring); bool addHandler(const BaseString &logstring, int *err, int len, char* errStr);
/** /**
* Remove a log handler. * Remove a log handler.

View File

@ -992,6 +992,22 @@ extern "C" {
int ndb_mgm_alloc_nodeid(NdbMgmHandle handle, int ndb_mgm_alloc_nodeid(NdbMgmHandle handle,
unsigned version, int nodetype); unsigned version, int nodetype);
/**
* End Session
*
* This function tells the mgm server to free all resources associated with
* this connection. It will also close it.
*
* This differs from just disconnecting as we now synchronously clean up,
* so that a quickly restarting server that needs the same node id can
* get it when it restarts.
*
* @param handle NDB management handle
* @return 0 on success
*
* @note you still have to destroy the NdbMgmHandle.
*/
int ndb_mgm_end_session(NdbMgmHandle handle);
/** /**
* Get the node id of the mgm server we're connected to * Get the node id of the mgm server we're connected to

View File

@ -78,6 +78,7 @@ public:
const char *get_connectstring(char *buf, int buf_sz) const; const char *get_connectstring(char *buf, int buf_sz) const;
NdbMgmHandle get_mgmHandle() { return m_handle; }; NdbMgmHandle get_mgmHandle() { return m_handle; };
NdbMgmHandle* get_mgmHandlePtr() { return &m_handle; }; NdbMgmHandle* get_mgmHandlePtr() { return &m_handle; };
void end_session(bool end) { m_end_session= end; };
Uint32 get_configuration_nodeid() const; Uint32 get_configuration_nodeid() const;
private: private:
@ -92,6 +93,8 @@ private:
void setError(ErrorType, const char * errorMsg); void setError(ErrorType, const char * errorMsg);
Uint32 _ownNodeId; Uint32 _ownNodeId;
bool m_end_session;
/* /*
Uint32 m_mgmd_port; Uint32 m_mgmd_port;
const char *m_mgmd_host; const char *m_mgmd_host;

View File

@ -187,6 +187,7 @@ FileLogHandler::setParam(const BaseString &param, const BaseString &value){
return setMaxSize(value); return setMaxSize(value);
if(param == "maxfiles") if(param == "maxfiles")
return setMaxFiles(value); return setMaxFiles(value);
setErrorStr("Invalid parameter");
return false; return false;
} }
@ -196,16 +197,18 @@ FileLogHandler::setFilename(const BaseString &filename) {
if(m_pLogFile) if(m_pLogFile)
delete m_pLogFile; delete m_pLogFile;
m_pLogFile = new File_class(filename.c_str(), "a+"); m_pLogFile = new File_class(filename.c_str(), "a+");
open(); return open();
return true;
} }
bool bool
FileLogHandler::setMaxSize(const BaseString &size) { FileLogHandler::setMaxSize(const BaseString &size) {
char *end; char *end;
long val = strtol(size.c_str(), &end, 0); /* XXX */ long val = strtol(size.c_str(), &end, 0); /* XXX */
if(size.c_str() == end) if(size.c_str() == end || val < 0)
{
setErrorStr("Invalid file size");
return false; return false;
}
if(end[0] == 'M') if(end[0] == 'M')
val *= 1024*1024; val *= 1024*1024;
if(end[0] == 'k') if(end[0] == 'k')
@ -220,8 +223,11 @@ bool
FileLogHandler::setMaxFiles(const BaseString &files) { FileLogHandler::setMaxFiles(const BaseString &files) {
char *end; char *end;
long val = strtol(files.c_str(), &end, 0); long val = strtol(files.c_str(), &end, 0);
if(files.c_str() == end) if(files.c_str() == end || val < 1)
{
setErrorStr("Invalid maximum number of files");
return false; return false;
}
m_maxNoFiles = val; m_maxNoFiles = val;
return true; return true;
@ -230,6 +236,9 @@ FileLogHandler::setMaxFiles(const BaseString &files) {
bool bool
FileLogHandler::checkParams() { FileLogHandler::checkParams() {
if(m_pLogFile == NULL) if(m_pLogFile == NULL)
{
setErrorStr("Log file cannot be null.");
return false; return false;
}
return true; return true;
} }

View File

@ -23,7 +23,8 @@
// //
LogHandler::LogHandler() : LogHandler::LogHandler() :
m_pDateTimeFormat("%d-%.2d-%.2d %.2d:%.2d:%.2d"), m_pDateTimeFormat("%d-%.2d-%.2d %.2d:%.2d:%.2d"),
m_errorCode(0) m_errorCode(0),
m_errorStr(NULL)
{ {
m_max_repeat_frequency= 3; // repeat messages maximum every 3 seconds m_max_repeat_frequency= 3; // repeat messages maximum every 3 seconds
m_count_repeated_messages= 0; m_count_repeated_messages= 0;
@ -155,6 +156,19 @@ LogHandler::setErrorCode(int code)
m_errorCode = code; m_errorCode = code;
} }
char*
LogHandler::getErrorStr()
{
return m_errorStr;
}
void
LogHandler::setErrorStr(char* str)
{
m_errorStr= str;
}
bool bool
LogHandler::parseParams(const BaseString &_params) { LogHandler::parseParams(const BaseString &_params) {
Vector<BaseString> v_args; Vector<BaseString> v_args;
@ -165,9 +179,18 @@ LogHandler::parseParams(const BaseString &_params) {
for(size_t i=0; i < v_args.size(); i++) { for(size_t i=0; i < v_args.size(); i++) {
Vector<BaseString> v_param_value; Vector<BaseString> v_param_value;
if(v_args[i].split(v_param_value, "=", 2) != 2) if(v_args[i].split(v_param_value, "=", 2) != 2)
{
ret = false; ret = false;
else if (!setParam(v_param_value[0], v_param_value[1])) setErrorStr("Can't find key=value pair.");
ret = false; }
else
{
v_param_value[0].trim(" \t");
if (!setParam(v_param_value[0], v_param_value[1]))
{
ret = false;
}
}
} }
if(!checkParams()) if(!checkParams())

View File

@ -167,7 +167,7 @@ Logger::addHandler(LogHandler* pHandler)
} }
bool bool
Logger::addHandler(const BaseString &logstring) { Logger::addHandler(const BaseString &logstring, int *err, int len, char* errStr) {
size_t i; size_t i;
Vector<BaseString> logdest; Vector<BaseString> logdest;
Vector<LogHandler *>loghandlers; Vector<LogHandler *>loghandlers;
@ -200,9 +200,18 @@ Logger::addHandler(const BaseString &logstring) {
handler = new ConsoleLogHandler(); handler = new ConsoleLogHandler();
if(handler == NULL) if(handler == NULL)
{
snprintf(errStr,len,"Could not create log destination: %s",
logdest[i].c_str());
DBUG_RETURN(false); DBUG_RETURN(false);
}
if(!handler->parseParams(params)) if(!handler->parseParams(params))
{
*err= handler->getErrorCode();
if(handler->getErrorStr())
strncpy(errStr, handler->getErrorStr(), len);
DBUG_RETURN(false); DBUG_RETURN(false);
}
loghandlers.push_back(handler); loghandlers.push_back(handler);
} }

View File

@ -154,5 +154,6 @@ SysLogHandler::setFacility(const BaseString &facility) {
return true; return true;
} }
} }
setErrorStr("Invalid syslog facility name");
return false; return false;
} }

View File

@ -52,6 +52,7 @@ ConfigRetriever::ConfigRetriever(const char * _connect_string,
m_version = version; m_version = version;
m_node_type = node_type; m_node_type = node_type;
_ownNodeId= 0; _ownNodeId= 0;
m_end_session= true;
m_handle= ndb_mgm_create_handle(); m_handle= ndb_mgm_create_handle();
@ -76,6 +77,8 @@ ConfigRetriever::~ConfigRetriever()
{ {
DBUG_ENTER("ConfigRetriever::~ConfigRetriever"); DBUG_ENTER("ConfigRetriever::~ConfigRetriever");
if (m_handle) { if (m_handle) {
if(m_end_session)
ndb_mgm_end_session(m_handle);
ndb_mgm_disconnect(m_handle); ndb_mgm_disconnect(m_handle);
ndb_mgm_destroy_handle(&m_handle); ndb_mgm_destroy_handle(&m_handle);
} }

View File

@ -42,6 +42,8 @@ SocketServer::~SocketServer() {
delete m_sessions[i].m_session; delete m_sessions[i].m_session;
} }
for(i = 0; i<m_services.size(); i++){ for(i = 0; i<m_services.size(); i++){
if(m_services[i].m_socket)
NDB_CLOSE_SOCKET(m_services[i].m_socket);
delete m_services[i].m_service; delete m_services[i].m_service;
} }
} }

View File

@ -307,8 +307,11 @@ int main(int argc, char** argv)
/** /**
* We no longer need the mgm connection in this process * We no longer need the mgm connection in this process
* (as we are the angel, not ndb) * (as we are the angel, not ndb)
*
* We don't want to purge any allocated resources (nodeid), so
* we set that option to false
*/ */
theConfig->closeConfiguration(); theConfig->closeConfiguration(false);
int status = 0, error_exit = 0, signum = 0; int status = 0, error_exit = 0, signum = 0;
while(waitpid(child, &status, 0) != child); while(waitpid(child, &status, 0) != child);

View File

@ -172,7 +172,8 @@ Configuration::~Configuration(){
} }
void void
Configuration::closeConfiguration(){ Configuration::closeConfiguration(bool end_session){
m_config_retriever->end_session(end_session);
if (m_config_retriever) { if (m_config_retriever) {
delete m_config_retriever; delete m_config_retriever;
} }

View File

@ -35,7 +35,7 @@ public:
void fetch_configuration(); void fetch_configuration();
void setupConfiguration(); void setupConfiguration();
void closeConfiguration(); void closeConfiguration(bool end_session= true);
bool lockPagesInMainMemory() const; bool lockPagesInMainMemory() const;

View File

@ -2321,4 +2321,23 @@ int ndb_mgm_report_event(NdbMgmHandle handle, Uint32 *data, Uint32 length)
DBUG_RETURN(0); DBUG_RETURN(0);
} }
extern "C"
int ndb_mgm_end_session(NdbMgmHandle handle)
{
DBUG_ENTER("ndb_mgm_end_session");
CHECK_HANDLE(handle, 0);
CHECK_CONNECTED(handle, 0);
SocketOutputStream s_output(handle->socket);
s_output.println("end session");
s_output.println("");
SocketInputStream in(handle->socket, handle->read_timeout);
char buf[32];
in.gets(buf, sizeof(buf));
DBUG_RETURN(0);
}
template class Vector<const ParserRow<ParserDummy>*>; template class Vector<const ParserRow<ParserDummy>*>;

View File

@ -928,26 +928,21 @@ CommandInterpreter::executeShutdown(char* parameters)
int result = 0; int result = 0;
result = ndb_mgm_stop(m_mgmsrv, 0, 0); result = ndb_mgm_stop(m_mgmsrv, 0, 0);
if (result < 0) { if (result < 0) {
ndbout << "Shutdown off NDB Cluster storage node(s) failed." << endl; ndbout << "Shutdown of NDB Cluster node(s) failed." << endl;
printError(); printError();
return result; return result;
} }
ndbout << result << " NDB Cluster storage node(s) have shutdown." << endl; ndbout << result << " NDB Cluster node(s) have shutdown." << endl;
int mgm_id= 0; int mgm_id= 0;
for(int i=0; i < state->no_of_nodes; i++) { mgm_id= ndb_mgm_get_mgmd_nodeid(m_mgmsrv);
if(state->node_states[i].node_type == NDB_MGM_NODE_TYPE_MGM && if (mgm_id == 0)
state->node_states[i].version != 0){ {
if (mgm_id == 0) ndbout << "Unable to locate management server, "
mgm_id= state->node_states[i].node_id; << "shutdown manually with <id> STOP"
else { << endl;
ndbout << "Unable to locate management server, " return 1;
<< "shutdown manually with <id> STOP"
<< endl;
return 1;
}
}
} }
result = ndb_mgm_stop(m_mgmsrv, 1, &mgm_id); result = ndb_mgm_stop(m_mgmsrv, 1, &mgm_id);

View File

@ -60,6 +60,9 @@
#include <SignalSender.hpp> #include <SignalSender.hpp>
extern bool g_StopServer;
extern bool g_RestartServer;
//#define MGM_SRV_DEBUG //#define MGM_SRV_DEBUG
#ifdef MGM_SRV_DEBUG #ifdef MGM_SRV_DEBUG
#define DEBUG(x) do ndbout << x << endl; while(0) #define DEBUG(x) do ndbout << x << endl; while(0)
@ -179,6 +182,8 @@ MgmtSrvr::startEventLog()
} }
const char * tmp; const char * tmp;
char errStr[100];
int err= 0;
BaseString logdest; BaseString logdest;
char *clusterLog= NdbConfig_ClusterLogFileName(_ownNodeId); char *clusterLog= NdbConfig_ClusterLogFileName(_ownNodeId);
NdbAutoPtr<char> tmp_aptr(clusterLog); NdbAutoPtr<char> tmp_aptr(clusterLog);
@ -192,9 +197,17 @@ MgmtSrvr::startEventLog()
logdest.assfmt("FILE:filename=%s,maxsize=1000000,maxfiles=6", logdest.assfmt("FILE:filename=%s,maxsize=1000000,maxfiles=6",
clusterLog); clusterLog);
} }
if(!g_eventLogger.addHandler(logdest)) { errStr[0]='\0';
if(!g_eventLogger.addHandler(logdest, &err, sizeof(errStr), errStr)) {
ndbout << "Warning: could not add log destination \"" ndbout << "Warning: could not add log destination \""
<< logdest.c_str() << "\"" << endl; << logdest.c_str() << "\". Reason: ";
if(err)
ndbout << strerror(err);
if(err && errStr[0]!='\0')
ndbout << ", ";
if(errStr[0]!='\0')
ndbout << errStr;
ndbout << endl;
} }
} }
@ -373,7 +386,8 @@ MgmtSrvr::MgmtSrvr(SocketServer *socket_server,
_ownReference(0), _ownReference(0),
theSignalIdleList(NULL), theSignalIdleList(NULL),
theWaitState(WAIT_SUBSCRIBE_CONF), theWaitState(WAIT_SUBSCRIBE_CONF),
m_event_listner(this) m_event_listner(this),
m_local_mgm_handle(0)
{ {
DBUG_ENTER("MgmtSrvr::MgmtSrvr"); DBUG_ENTER("MgmtSrvr::MgmtSrvr");
@ -537,6 +551,8 @@ MgmtSrvr::check_start()
bool bool
MgmtSrvr::start(BaseString &error_string) MgmtSrvr::start(BaseString &error_string)
{ {
int mgm_connect_result;
DBUG_ENTER("MgmtSrvr::start"); DBUG_ENTER("MgmtSrvr::start");
if (_props == NULL) { if (_props == NULL) {
if (!check_start()) { if (!check_start()) {
@ -574,6 +590,13 @@ MgmtSrvr::start(BaseString &error_string)
DBUG_RETURN(false); DBUG_RETURN(false);
} }
if((mgm_connect_result= connect_to_self()) < 0)
{
ndbout_c("Unable to connect to our own ndb_mgmd (Error %d)",
mgm_connect_result);
ndbout_c("This is probably a bug.");
}
TransporterRegistry *reg = theFacade->get_registry(); TransporterRegistry *reg = theFacade->get_registry();
for(unsigned int i=0;i<reg->m_transporter_interface.size();i++) { for(unsigned int i=0;i<reg->m_transporter_interface.size();i++) {
BaseString msg; BaseString msg;
@ -831,9 +854,81 @@ MgmtSrvr::sendVersionReq(int v_nodeId, Uint32 &version, const char **address)
return 0; return 0;
} }
int MgmtSrvr::sendStopMgmd(NodeId nodeId,
bool abort,
bool stop,
bool restart,
bool nostart,
bool initialStart)
{
const char* hostname;
Uint32 port;
BaseString connect_string;
{
Guard g(m_configMutex);
{
ndb_mgm_configuration_iterator
iter(* _config->m_configValues, CFG_SECTION_NODE);
if(iter.first()) return SEND_OR_RECEIVE_FAILED;
if(iter.find(CFG_NODE_ID, nodeId)) return SEND_OR_RECEIVE_FAILED;
if(iter.get(CFG_NODE_HOST, &hostname)) return SEND_OR_RECEIVE_FAILED;
}
{
ndb_mgm_configuration_iterator
iter(* _config->m_configValues, CFG_SECTION_NODE);
if(iter.first()) return SEND_OR_RECEIVE_FAILED;
if(iter.find(CFG_NODE_ID, nodeId)) return SEND_OR_RECEIVE_FAILED;
if(iter.get(CFG_MGM_PORT, &port)) return SEND_OR_RECEIVE_FAILED;
}
if( strlen(hostname) == 0 )
return SEND_OR_RECEIVE_FAILED;
}
connect_string.assfmt("%s:%u",hostname,port);
DBUG_PRINT("info",("connect string: %s",connect_string.c_str()));
NdbMgmHandle h= ndb_mgm_create_handle();
if ( h && connect_string.length() > 0 )
{
ndb_mgm_set_connectstring(h,connect_string.c_str());
if(ndb_mgm_connect(h,1,0,0))
{
DBUG_PRINT("info",("failed ndb_mgm_connect"));
return SEND_OR_RECEIVE_FAILED;
}
if(!restart)
{
if(ndb_mgm_stop(h, 1, (const int*)&nodeId) < 0)
{
return SEND_OR_RECEIVE_FAILED;
}
}
else
{
int nodes[1];
nodes[0]= (int)nodeId;
if(ndb_mgm_restart2(h, 1, nodes, initialStart, nostart, abort) < 0)
{
return SEND_OR_RECEIVE_FAILED;
}
}
}
ndb_mgm_destroy_handle(&h);
return 0;
}
/* /*
* Common method for handeling all STOP_REQ signalling that * Common method for handeling all STOP_REQ signalling that
* is used by Stopping, Restarting and Single user commands * is used by Stopping, Restarting and Single user commands
*
* In the event that we need to stop a mgmd, we create a mgm
* client connection to that mgmd and stop it that way.
* This allows us to stop mgm servers when there isn't any real
* distributed communication up.
*/ */
int MgmtSrvr::sendSTOP_REQ(NodeId nodeId, int MgmtSrvr::sendSTOP_REQ(NodeId nodeId,
@ -845,6 +940,8 @@ int MgmtSrvr::sendSTOP_REQ(NodeId nodeId,
bool nostart, bool nostart,
bool initialStart) bool initialStart)
{ {
int error = 0;
stoppedNodes.clear(); stoppedNodes.clear();
SignalSender ss(theFacade); SignalSender ss(theFacade);
@ -883,18 +980,34 @@ int MgmtSrvr::sendSTOP_REQ(NodeId nodeId,
NodeBitmask nodes; NodeBitmask nodes;
if (nodeId) if (nodeId)
{ {
if(nodeId==getOwnNodeId())
{
if(restart)
g_RestartServer= true;
g_StopServer= true;
return 0;
}
if(getNodeType(nodeId) == NDB_MGM_NODE_TYPE_NDB)
{ {
int r; int r;
if((r = okToSendTo(nodeId, true)) != 0) if((r= okToSendTo(nodeId, true)) != 0)
return r; return r;
}
{
if (ss.sendSignal(nodeId, &ssig) != SEND_OK) if (ss.sendSignal(nodeId, &ssig) != SEND_OK)
return SEND_OR_RECEIVE_FAILED; return SEND_OR_RECEIVE_FAILED;
} }
else if(getNodeType(nodeId) == NDB_MGM_NODE_TYPE_MGM)
{
error= sendStopMgmd(nodeId, abort, stop, restart, nostart, initialStart);
if(error==0)
stoppedNodes.set(nodeId);
return error;
}
else
return WRONG_PROCESS_TYPE;
nodes.set(nodeId); nodes.set(nodeId);
} }
else else
{
while(getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)) while(getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB))
{ {
if(okToSendTo(nodeId, true) == 0) if(okToSendTo(nodeId, true) == 0)
@ -904,9 +1017,17 @@ int MgmtSrvr::sendSTOP_REQ(NodeId nodeId,
nodes.set(nodeId); nodes.set(nodeId);
} }
} }
nodeId= 0;
while(getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_MGM))
{
if(nodeId==getOwnNodeId())
continue;
if(sendStopMgmd(nodeId, abort, stop, restart, nostart, initialStart)==0)
stoppedNodes.set(nodeId);
}
}
// now wait for the replies // now wait for the replies
int error = 0;
while (!nodes.isclear()) while (!nodes.isclear())
{ {
SimpleSignal *signal = ss.waitFor(); SimpleSignal *signal = ss.waitFor();
@ -2552,9 +2673,23 @@ void MgmtSrvr::transporter_connect(NDB_SOCKET_TYPE sockfd)
} }
} }
int MgmtSrvr::set_connect_string(const char *str) int MgmtSrvr::connect_to_self(void)
{ {
return ndb_mgm_set_connectstring(m_config_retriever->get_mgmHandle(),str); int r= 0;
m_local_mgm_handle= ndb_mgm_create_handle();
snprintf(m_local_mgm_connect_string,sizeof(m_local_mgm_connect_string),
"localhost:%u",getPort());
ndb_mgm_set_connectstring(m_local_mgm_handle, m_local_mgm_connect_string);
if((r= ndb_mgm_connect(m_local_mgm_handle, 0, 0, 0)) < 0)
{
ndb_mgm_destroy_handle(&m_local_mgm_handle);
return r;
}
// TransporterRegistry now owns this NdbMgmHandle and will destroy it.
theFacade->get_registry()->set_mgm_handle(m_local_mgm_handle);
return 0;
} }

View File

@ -466,7 +466,7 @@ public:
int getConnectionDbParameter(int node1, int node2, int param, int getConnectionDbParameter(int node1, int node2, int param,
int *value, BaseString& msg); int *value, BaseString& msg);
int set_connect_string(const char *str); int connect_to_self(void);
void transporter_connect(NDB_SOCKET_TYPE sockfd); void transporter_connect(NDB_SOCKET_TYPE sockfd);
@ -482,6 +482,13 @@ private:
int send(SignalSender &ss, SimpleSignal &ssig, Uint32 node, Uint32 node_type); int send(SignalSender &ss, SimpleSignal &ssig, Uint32 node, Uint32 node_type);
int sendStopMgmd(NodeId nodeId,
bool abort,
bool stop,
bool restart,
bool nostart,
bool initialStart);
int sendSTOP_REQ(NodeId nodeId, int sendSTOP_REQ(NodeId nodeId,
NodeBitmask &stoppedNodes, NodeBitmask &stoppedNodes,
Uint32 singleUserNodeId, Uint32 singleUserNodeId,
@ -625,6 +632,8 @@ private:
// signal arrives. // signal arrives.
// We wait in receiveOptimisedResponse and signal in handleReceivedSignal. // We wait in receiveOptimisedResponse and signal in handleReceivedSignal.
NdbMgmHandle m_local_mgm_handle;
char m_local_mgm_connect_string[20];
class TransporterFacade * theFacade; class TransporterFacade * theFacade;
int sendVersionReq( int processId, Uint32 &version, const char **address); int sendVersionReq( int processId, Uint32 &version, const char **address);

View File

@ -203,6 +203,8 @@ ParserRow<MgmApiSession> commands[] = {
MGM_CMD("bye", &MgmApiSession::bye, ""), MGM_CMD("bye", &MgmApiSession::bye, ""),
MGM_CMD("end session", &MgmApiSession::endSession, ""),
MGM_CMD("set loglevel", &MgmApiSession::setLogLevel, ""), MGM_CMD("set loglevel", &MgmApiSession::setLogLevel, ""),
MGM_ARG("node", Int, Mandatory, "Node"), MGM_ARG("node", Int, Mandatory, "Node"),
MGM_ARG("category", Int, Mandatory, "Event category"), MGM_ARG("category", Int, Mandatory, "Event category"),
@ -719,10 +721,21 @@ MgmApiSession::dumpState(Parser<MgmApiSession>::Context &,
void void
MgmApiSession::bye(Parser<MgmApiSession>::Context &, MgmApiSession::bye(Parser<MgmApiSession>::Context &,
Properties const &) { Properties const &) {
m_stop = true; m_stop = true;
} }
void
MgmApiSession::endSession(Parser<MgmApiSession>::Context &,
Properties const &) {
if(m_allocated_resources)
delete m_allocated_resources;
m_allocated_resources= new MgmtSrvr::Allocated_resources(m_mgmsrv);
m_output->println("end session reply");
}
void void
MgmApiSession::setClusterLogLevel(Parser<MgmApiSession>::Context &, MgmApiSession::setClusterLogLevel(Parser<MgmApiSession>::Context &,
Properties const &args) { Properties const &args) {

View File

@ -79,6 +79,7 @@ public:
void start(Parser_t::Context &ctx, const class Properties &args); void start(Parser_t::Context &ctx, const class Properties &args);
void startAll(Parser_t::Context &ctx, const class Properties &args); void startAll(Parser_t::Context &ctx, const class Properties &args);
void bye(Parser_t::Context &ctx, const class Properties &args); void bye(Parser_t::Context &ctx, const class Properties &args);
void endSession(Parser_t::Context &ctx, const class Properties &args);
void setLogLevel(Parser_t::Context &ctx, const class Properties &args); void setLogLevel(Parser_t::Context &ctx, const class Properties &args);
void setClusterLogLevel(Parser_t::Context &ctx, void setClusterLogLevel(Parser_t::Context &ctx,
const class Properties &args); const class Properties &args);

Some files were not shown because too many files have changed in this diff Show More