mirror of
https://github.com/MariaDB/server.git
synced 2025-01-17 12:32:27 +01:00
Merge osalerma@bk-internal.mysql.com:/home/bk/mysql-5.0
into 127.(none):/home/osku/mysql-5.0
This commit is contained in:
commit
b3dcaff948
33 changed files with 256 additions and 359 deletions
|
@ -203,7 +203,7 @@ static int com_nopager(String *str, char*), com_pager(String *str, char*),
|
||||||
com_edit(String *str,char*), com_shell(String *str, char *);
|
com_edit(String *str,char*), com_shell(String *str, char *);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int read_lines(bool execute_commands);
|
static int read_and_execute(bool interactive);
|
||||||
static int sql_connect(char *host,char *database,char *user,char *password,
|
static int sql_connect(char *host,char *database,char *user,char *password,
|
||||||
uint silent);
|
uint silent);
|
||||||
static int put_info(const char *str,INFO_TYPE info,uint error=0,
|
static int put_info(const char *str,INFO_TYPE info,uint error=0,
|
||||||
|
@ -468,7 +468,7 @@ int main(int argc,char *argv[])
|
||||||
"Type 'help [[%]function name[%]]' to get help on usage of function.\n");
|
"Type 'help [[%]function name[%]]' to get help on usage of function.\n");
|
||||||
#endif
|
#endif
|
||||||
put_info(buff,INFO_INFO);
|
put_info(buff,INFO_INFO);
|
||||||
status.exit_status=read_lines(1); // read lines and execute them
|
status.exit_status= read_and_execute(!status.batch);
|
||||||
if (opt_outfile)
|
if (opt_outfile)
|
||||||
end_tee();
|
end_tee();
|
||||||
mysql_end(0);
|
mysql_end(0);
|
||||||
|
@ -957,7 +957,7 @@ static int get_options(int argc, char **argv)
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int read_lines(bool execute_commands)
|
static int read_and_execute(bool interactive)
|
||||||
{
|
{
|
||||||
#if defined( __WIN__) || defined(OS2) || defined(__NETWARE__)
|
#if defined( __WIN__) || defined(OS2) || defined(__NETWARE__)
|
||||||
char linebuffer[254];
|
char linebuffer[254];
|
||||||
|
@ -972,7 +972,7 @@ static int read_lines(bool execute_commands)
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
if (status.batch || !execute_commands)
|
if (!interactive)
|
||||||
{
|
{
|
||||||
line=batch_readline(status.line_buff);
|
line=batch_readline(status.line_buff);
|
||||||
line_number++;
|
line_number++;
|
||||||
|
@ -1050,7 +1050,7 @@ static int read_lines(bool execute_commands)
|
||||||
Check if line is a mysql command line
|
Check if line is a mysql command line
|
||||||
(We want to allow help, print and clear anywhere at line start
|
(We want to allow help, print and clear anywhere at line start
|
||||||
*/
|
*/
|
||||||
if (execute_commands && (named_cmds || glob_buffer.is_empty())
|
if ((named_cmds || glob_buffer.is_empty())
|
||||||
&& !in_string && (com=find_command(line,0)))
|
&& !in_string && (com=find_command(line,0)))
|
||||||
{
|
{
|
||||||
if ((*com->func)(&glob_buffer,line) > 0)
|
if ((*com->func)(&glob_buffer,line) > 0)
|
||||||
|
@ -1058,7 +1058,7 @@ static int read_lines(bool execute_commands)
|
||||||
if (glob_buffer.is_empty()) // If buffer was emptied
|
if (glob_buffer.is_empty()) // If buffer was emptied
|
||||||
in_string=0;
|
in_string=0;
|
||||||
#ifdef HAVE_READLINE
|
#ifdef HAVE_READLINE
|
||||||
if (status.add_to_history && not_in_history(line))
|
if (interactive && status.add_to_history && not_in_history(line))
|
||||||
add_history(line);
|
add_history(line);
|
||||||
#endif
|
#endif
|
||||||
continue;
|
continue;
|
||||||
|
@ -1068,7 +1068,7 @@ static int read_lines(bool execute_commands)
|
||||||
}
|
}
|
||||||
/* if in batch mode, send last query even if it doesn't end with \g or go */
|
/* if in batch mode, send last query even if it doesn't end with \g or go */
|
||||||
|
|
||||||
if ((status.batch || !execute_commands) && !status.exit_status)
|
if (!interactive && !status.exit_status)
|
||||||
{
|
{
|
||||||
remove_cntrl(glob_buffer);
|
remove_cntrl(glob_buffer);
|
||||||
if (!glob_buffer.is_empty())
|
if (!glob_buffer.is_empty())
|
||||||
|
@ -2783,7 +2783,7 @@ static int com_source(String *buffer, char *line)
|
||||||
status.line_buff=line_buff;
|
status.line_buff=line_buff;
|
||||||
status.file_name=source_name;
|
status.file_name=source_name;
|
||||||
glob_buffer.length(0); // Empty command buffer
|
glob_buffer.length(0); // Empty command buffer
|
||||||
error=read_lines(0); // Read lines from file
|
error= read_and_execute(false);
|
||||||
status=old_status; // Continue as before
|
status=old_status; // Continue as before
|
||||||
my_fclose(sql_file,MYF(0));
|
my_fclose(sql_file,MYF(0));
|
||||||
batch_readline_end(line_buff);
|
batch_readline_end(line_buff);
|
||||||
|
|
|
@ -523,6 +523,10 @@ alter table t1 drop key no_such_key;
|
||||||
ERROR 42000: Can't DROP 'no_such_key'; check that column/key exists
|
ERROR 42000: Can't DROP 'no_such_key'; check that column/key exists
|
||||||
alter table t1 drop key a;
|
alter table t1 drop key a;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
CREATE TABLE T12207(a int) ENGINE=MYISAM;
|
||||||
|
ALTER TABLE T12207 DISCARD TABLESPACE;
|
||||||
|
ERROR HY000: Table storage engine for 'T12207' doesn't have this option
|
||||||
|
DROP TABLE T12207;
|
||||||
create table t1 (a text) character set koi8r;
|
create table t1 (a text) character set koi8r;
|
||||||
insert into t1 values (_koi8r'ÔÅÓÔ');
|
insert into t1 values (_koi8r'ÔÅÓÔ');
|
||||||
select hex(a) from t1;
|
select hex(a) from t1;
|
||||||
|
|
|
@ -31,6 +31,10 @@ a
|
||||||
Test delimiter delimiter
|
Test delimiter delimiter
|
||||||
a
|
a
|
||||||
1
|
1
|
||||||
|
Tables_in_test
|
||||||
|
t1
|
||||||
|
t2
|
||||||
|
t3
|
||||||
|
|
||||||
Test delimiter : from command line
|
Test delimiter : from command line
|
||||||
a
|
a
|
||||||
|
|
|
@ -2875,6 +2875,16 @@ b a t1_val t2_val
|
||||||
1 1 1 1
|
1 1 1 1
|
||||||
1 2 2 1
|
1 2 2 1
|
||||||
drop table t1, t2, t3;
|
drop table t1, t2, t3;
|
||||||
|
DO IFNULL(NULL, NULL);
|
||||||
|
SELECT CAST(IFNULL(NULL, NULL) AS DECIMAL);
|
||||||
|
CAST(IFNULL(NULL, NULL) AS DECIMAL)
|
||||||
|
NULL
|
||||||
|
SELECT ABS(IFNULL(NULL, NULL));
|
||||||
|
ABS(IFNULL(NULL, NULL))
|
||||||
|
NULL
|
||||||
|
SELECT IFNULL(NULL, NULL);
|
||||||
|
IFNULL(NULL, NULL)
|
||||||
|
NULL
|
||||||
create table t1 (a char(1));
|
create table t1 (a char(1));
|
||||||
create table t2 (a char(1));
|
create table t2 (a char(1));
|
||||||
insert into t1 values ('a'),('b'),('c');
|
insert into t1 values ('a'),('b'),('c');
|
||||||
|
|
|
@ -748,6 +748,14 @@ end|
|
||||||
call bug11394(2, 1)|
|
call bug11394(2, 1)|
|
||||||
ERROR HY000: Recursive stored routines are not allowed.
|
ERROR HY000: Recursive stored routines are not allowed.
|
||||||
drop procedure bug11394|
|
drop procedure bug11394|
|
||||||
|
CREATE PROCEDURE BUG_12490() HELP CONTENTS;
|
||||||
|
ERROR 0A000: HELP is not allowed in stored procedures
|
||||||
|
CREATE FUNCTION BUG_12490() RETURNS INT HELP CONTENTS;
|
||||||
|
ERROR 0A000: HELP is not allowed in stored procedures
|
||||||
|
CREATE TABLE t_bug_12490(a int);
|
||||||
|
CREATE TRIGGER BUG_12490 BEFORE UPDATE ON t_bug_12490 FOR EACH ROW HELP CONTENTS;
|
||||||
|
ERROR 0A000: HELP is not allowed in stored procedures
|
||||||
|
DROP TABLE t_bug_12490;
|
||||||
drop function if exists bug11834_1;
|
drop function if exists bug11834_1;
|
||||||
drop function if exists bug11834_2;
|
drop function if exists bug11834_2;
|
||||||
create function bug11834_1() returns int return 10;
|
create function bug11834_1() returns int return 10;
|
||||||
|
|
|
@ -337,6 +337,14 @@ alter table t1 drop key no_such_key;
|
||||||
alter table t1 drop key a;
|
alter table t1 drop key a;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# BUG 12207 alter table ... discard table space on MyISAM table causes ERROR 2013 (HY000)
|
||||||
|
#
|
||||||
|
CREATE TABLE T12207(a int) ENGINE=MYISAM;
|
||||||
|
--error 1031
|
||||||
|
ALTER TABLE T12207 DISCARD TABLESPACE;
|
||||||
|
DROP TABLE T12207;
|
||||||
|
|
||||||
#
|
#
|
||||||
# Bug #6479 ALTER TABLE ... changing charset fails for TEXT columns
|
# Bug #6479 ALTER TABLE ... changing charset fails for TEXT columns
|
||||||
#
|
#
|
||||||
|
|
|
@ -45,4 +45,7 @@ delimiter delimiter
|
||||||
select * from t1 delimiter
|
select * from t1 delimiter
|
||||||
delimiter ; # Reset delimiter
|
delimiter ; # Reset delimiter
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug #11523: \d works differently than delimiter
|
||||||
|
#
|
||||||
|
source t/mysql_delimiter_source.sql
|
||||||
|
|
8
mysql-test/t/mysql_delimiter_source.sql
Normal file
8
mysql-test/t/mysql_delimiter_source.sql
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
delimiter //
|
||||||
|
create table t2 (a int) //
|
||||||
|
delimiter ;
|
||||||
|
\d //
|
||||||
|
create table t3 (a int) //
|
||||||
|
\d ;
|
||||||
|
show tables;
|
||||||
|
drop table t2, t3;
|
|
@ -2445,6 +2445,15 @@ select * from t1 natural join t3 natural join t2;
|
||||||
drop table t1, t2, t3;
|
drop table t1, t2, t3;
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug #12841: Server crash on DO IFNULL(NULL,NULL)
|
||||||
|
#
|
||||||
|
# (testing returning of int, decimal, real, string)
|
||||||
|
DO IFNULL(NULL, NULL);
|
||||||
|
SELECT CAST(IFNULL(NULL, NULL) AS DECIMAL);
|
||||||
|
SELECT ABS(IFNULL(NULL, NULL));
|
||||||
|
SELECT IFNULL(NULL, NULL);
|
||||||
|
|
||||||
#
|
#
|
||||||
# Bug #6495 Illogical requirement for column qualification in NATURAL join
|
# Bug #6495 Illogical requirement for column qualification in NATURAL join
|
||||||
#
|
#
|
||||||
|
|
|
@ -1079,6 +1079,19 @@ call bug11394(2, 1)|
|
||||||
drop procedure bug11394|
|
drop procedure bug11394|
|
||||||
delimiter ;|
|
delimiter ;|
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# BUG 12490 (Packets out of order if calling HELP CONTENTS from Stored Procedure)
|
||||||
|
#
|
||||||
|
--error 1314
|
||||||
|
CREATE PROCEDURE BUG_12490() HELP CONTENTS;
|
||||||
|
--error 1314
|
||||||
|
CREATE FUNCTION BUG_12490() RETURNS INT HELP CONTENTS;
|
||||||
|
CREATE TABLE t_bug_12490(a int);
|
||||||
|
--error 1314
|
||||||
|
CREATE TRIGGER BUG_12490 BEFORE UPDATE ON t_bug_12490 FOR EACH ROW HELP CONTENTS;
|
||||||
|
DROP TABLE t_bug_12490;
|
||||||
|
|
||||||
#
|
#
|
||||||
# Bug#11834 "Re-execution of prepared statement with dropped function
|
# Bug#11834 "Re-execution of prepared statement with dropped function
|
||||||
# crashes server". Also tests handling of prepared stmts which use
|
# crashes server". Also tests handling of prepared stmts which use
|
||||||
|
|
|
@ -509,7 +509,7 @@ ALTER TABLE proc MODIFY name char(64) DEFAULT '' NOT NULL,
|
||||||
'TRADITIONAL',
|
'TRADITIONAL',
|
||||||
'NO_AUTO_CREATE_USER',
|
'NO_AUTO_CREATE_USER',
|
||||||
'HIGH_NOT_PRECEDENCE'
|
'HIGH_NOT_PRECEDENCE'
|
||||||
) DEFAULT '' NOT NULL
|
) DEFAULT '' NOT NULL,
|
||||||
DEFAULT CHARACTER SET utf8;
|
DEFAULT CHARACTER SET utf8;
|
||||||
|
|
||||||
# Correct the character set and collation
|
# Correct the character set and collation
|
||||||
|
|
|
@ -70,7 +70,6 @@ mysqlmanager_SOURCES= command.cc command.h mysqlmanager.cc \
|
||||||
user_map.h user_map.cc \
|
user_map.h user_map.cc \
|
||||||
messages.h messages.cc \
|
messages.h messages.cc \
|
||||||
commands.h commands.cc \
|
commands.h commands.cc \
|
||||||
factory.h factory.cc \
|
|
||||||
instance.h instance.cc \
|
instance.h instance.cc \
|
||||||
instance_map.h instance_map.cc\
|
instance_map.h instance_map.cc\
|
||||||
instance_options.h instance_options.cc \
|
instance_options.h instance_options.cc \
|
||||||
|
|
|
@ -461,7 +461,8 @@ int Show_instance_log::execute(struct st_net *net, ulong connection_id)
|
||||||
/* Instance has no such log */
|
/* Instance has no such log */
|
||||||
if (logpath == NULL)
|
if (logpath == NULL)
|
||||||
return ER_NO_SUCH_LOG;
|
return ER_NO_SUCH_LOG;
|
||||||
else if (*logpath == '\0')
|
|
||||||
|
if (*logpath == '\0')
|
||||||
return ER_GUESS_LOGFILE;
|
return ER_GUESS_LOGFILE;
|
||||||
|
|
||||||
|
|
||||||
|
@ -571,6 +572,7 @@ int Show_instance_log_files::execute(struct st_net *net, ulong connection_id)
|
||||||
if ((instance= instance_map->
|
if ((instance= instance_map->
|
||||||
find(instance_name, strlen(instance_name))) == NULL)
|
find(instance_name, strlen(instance_name))) == NULL)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
We have alike structure in instance_options.cc. We use such to be able
|
We have alike structure in instance_options.cc. We use such to be able
|
||||||
|
@ -686,7 +688,7 @@ Set_option::Set_option(Instance_map *instance_map_arg,
|
||||||
option.
|
option.
|
||||||
|
|
||||||
RETURN
|
RETURN
|
||||||
ER_BAD_INSTANCE_NAME The instance name specified is not valid
|
ER_OUT_OF_RESOURCES out of resources
|
||||||
ER_ACCESS_OPTION_FILE Cannot access the option file
|
ER_ACCESS_OPTION_FILE Cannot access the option file
|
||||||
0 - ok
|
0 - ok
|
||||||
*/
|
*/
|
||||||
|
@ -694,22 +696,14 @@ Set_option::Set_option(Instance_map *instance_map_arg,
|
||||||
int Set_option::correct_file(int skip)
|
int Set_option::correct_file(int skip)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
|
const static int mysys_to_im_error[]= { 0, ER_OUT_OF_RESOURCES,
|
||||||
|
ER_ACCESS_OPTION_FILE };
|
||||||
|
|
||||||
error= modify_defaults_file(Options::config_file, option,
|
error= modify_defaults_file(Options::config_file, option,
|
||||||
option_value, instance_name, skip);
|
option_value, instance_name, skip);
|
||||||
switch (error)
|
DBUG_ASSERT(error >= 0 && error <= 2);
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
return 0; /* everything was fine */
|
|
||||||
case 1:
|
|
||||||
return ER_OUT_OF_RESOURCES;
|
|
||||||
case 2:
|
|
||||||
return ER_ACCESS_OPTION_FILE;
|
|
||||||
default:
|
|
||||||
DBUG_ASSERT(0); /* should never get here */
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0; /* keep compiler happy */
|
return mysys_to_im_error[error];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -725,10 +719,9 @@ int Set_option::correct_file(int skip)
|
||||||
1 - error occured
|
1 - error occured
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
int Set_option::do_command(struct st_net *net)
|
int Set_option::do_command(struct st_net *net)
|
||||||
{
|
{
|
||||||
int error= 0;
|
int error;
|
||||||
|
|
||||||
/* we must hold the instance_map mutex while changing config file */
|
/* we must hold the instance_map mutex while changing config file */
|
||||||
instance_map->lock();
|
instance_map->lock();
|
||||||
|
@ -746,16 +739,14 @@ int Set_option::execute(struct st_net *net, ulong connection_id)
|
||||||
int val;
|
int val;
|
||||||
|
|
||||||
val= do_command(net);
|
val= do_command(net);
|
||||||
|
|
||||||
if (val == 0)
|
if (val == 0)
|
||||||
{
|
|
||||||
net_send_ok(net, connection_id, NULL);
|
net_send_ok(net, connection_id, NULL);
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
return ER_BAD_INSTANCE_NAME;
|
return ER_BAD_INSTANCE_NAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -785,16 +776,15 @@ int Stop_instance::execute(struct st_net *net, ulong connection_id)
|
||||||
|
|
||||||
if (instance == 0)
|
if (instance == 0)
|
||||||
return ER_BAD_INSTANCE_NAME; /* haven't found an instance */
|
return ER_BAD_INSTANCE_NAME; /* haven't found an instance */
|
||||||
else
|
|
||||||
{
|
if (!(instance->options.nonguarded))
|
||||||
if (!(instance->options.nonguarded))
|
instance_map->guardian->stop_guard(instance);
|
||||||
instance_map->guardian->
|
|
||||||
stop_guard(instance);
|
if ((err_code= instance->stop()))
|
||||||
if ((err_code= instance->stop()))
|
return err_code;
|
||||||
return err_code;
|
|
||||||
net_send_ok(net, connection_id, NULL);
|
net_send_ok(net, connection_id, NULL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,100 +0,0 @@
|
||||||
/* Copyright (C) 2004 MySQL AB
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|
||||||
|
|
||||||
#include "factory.h"
|
|
||||||
|
|
||||||
|
|
||||||
Show_instances *Command_factory::new_Show_instances()
|
|
||||||
{
|
|
||||||
return new Show_instances(&instance_map);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Flush_instances *Command_factory::new_Flush_instances()
|
|
||||||
{
|
|
||||||
return new Flush_instances(&instance_map);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Show_instance_status *Command_factory::
|
|
||||||
new_Show_instance_status(const char *name, uint len)
|
|
||||||
{
|
|
||||||
return new Show_instance_status(&instance_map, name, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Show_instance_options *Command_factory::
|
|
||||||
new_Show_instance_options(const char *name, uint len)
|
|
||||||
{
|
|
||||||
return new Show_instance_options(&instance_map, name, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Start_instance *Command_factory::
|
|
||||||
new_Start_instance(const char *name, uint len)
|
|
||||||
{
|
|
||||||
return new Start_instance(&instance_map, name, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Stop_instance *Command_factory::new_Stop_instance(const char *name, uint len)
|
|
||||||
{
|
|
||||||
return new Stop_instance(&instance_map, name, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Syntax_error *Command_factory::new_Syntax_error()
|
|
||||||
{
|
|
||||||
return new Syntax_error();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Set_option *Command_factory::
|
|
||||||
new_Set_option(const char* name, uint len,
|
|
||||||
const char *option_arg, uint option_len,
|
|
||||||
const char *option_value_arg, uint option_value_len)
|
|
||||||
{
|
|
||||||
return new Set_option(&instance_map, name, len, option_arg,
|
|
||||||
option_len, option_value_arg, option_value_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Unset_option *Command_factory::
|
|
||||||
new_Unset_option(const char* name, uint len,
|
|
||||||
const char *option_arg, uint option_len,
|
|
||||||
const char *option_value_arg, uint option_value_len)
|
|
||||||
{
|
|
||||||
return new Unset_option(&instance_map, name, len, option_arg,
|
|
||||||
option_len, option_value_arg, option_value_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Show_instance_log *Command_factory::
|
|
||||||
new_Show_instance_log(const char *name, uint len,
|
|
||||||
Log_type log_type_arg,
|
|
||||||
const char *size, const char *offset)
|
|
||||||
{
|
|
||||||
return new Show_instance_log(&instance_map, name, len,
|
|
||||||
log_type_arg, size, offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Show_instance_log_files *Command_factory::
|
|
||||||
new_Show_instance_log_files(const char *name, uint len)
|
|
||||||
{
|
|
||||||
return new Show_instance_log_files(&instance_map, name, len);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,61 +0,0 @@
|
||||||
#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_FACTORY_H
|
|
||||||
#define INCLUDES_MYSQL_INSTANCE_MANAGER_FACTORY_H
|
|
||||||
/* Copyright (C) 2004 MySQL AB
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|
||||||
|
|
||||||
#include "command.h"
|
|
||||||
#include "commands.h"
|
|
||||||
#include "instance_map.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
This class could be used to handle various protocols. We could pass to
|
|
||||||
the parser various derived classes. I.e Mylsq_command_factory,
|
|
||||||
Http_command_factory e.t.c. Also see comment in the instance_map.cc
|
|
||||||
*/
|
|
||||||
|
|
||||||
class Show_instances;
|
|
||||||
|
|
||||||
class Command_factory
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Command_factory(Instance_map &instance_map): instance_map(instance_map)
|
|
||||||
{}
|
|
||||||
|
|
||||||
Show_instances *new_Show_instances ();
|
|
||||||
Flush_instances *new_Flush_instances ();
|
|
||||||
Syntax_error *new_Syntax_error ();
|
|
||||||
Show_instance_status *new_Show_instance_status (const char *name, uint len);
|
|
||||||
Show_instance_options *new_Show_instance_options (const char *name, uint len);
|
|
||||||
Start_instance *new_Start_instance (const char *name, uint len);
|
|
||||||
Stop_instance *new_Stop_instance (const char *name, uint len);
|
|
||||||
Show_instance_log *new_Show_instance_log (const char *name, uint len,
|
|
||||||
Log_type log_type_arg,
|
|
||||||
const char *size,
|
|
||||||
const char *offset);
|
|
||||||
Set_option *new_Set_option (const char *name, uint len,
|
|
||||||
const char *option_arg, uint option_len,
|
|
||||||
const char *option_value_arg,
|
|
||||||
uint option_value_len);
|
|
||||||
Unset_option *new_Unset_option (const char *name, uint len,
|
|
||||||
const char *option_arg, uint option_len,
|
|
||||||
const char *option_value_arg,
|
|
||||||
uint option_value_len);
|
|
||||||
Show_instance_log_files *new_Show_instance_log_files (const char *name,
|
|
||||||
uint len);
|
|
||||||
|
|
||||||
Instance_map &instance_map;
|
|
||||||
};
|
|
||||||
#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_FACTORY_H */
|
|
|
@ -122,8 +122,7 @@ void Guardian_thread::process_instance(Instance *instance,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
switch (current_node->state)
|
switch (current_node->state) {
|
||||||
{
|
|
||||||
case NOT_STARTED:
|
case NOT_STARTED:
|
||||||
instance->start();
|
instance->start();
|
||||||
current_node->last_checked= current_time;
|
current_node->last_checked= current_time;
|
||||||
|
@ -149,7 +148,8 @@ void Guardian_thread::process_instance(Instance *instance,
|
||||||
log_info("guardian: starting instance %s",
|
log_info("guardian: starting instance %s",
|
||||||
instance->options.instance_name);
|
instance->options.instance_name);
|
||||||
}
|
}
|
||||||
else current_node->state= CRASHED;
|
else
|
||||||
|
current_node->state= CRASHED;
|
||||||
break;
|
break;
|
||||||
case CRASHED: /* just regular restarts */
|
case CRASHED: /* just regular restarts */
|
||||||
if (current_time - current_node->last_checked >
|
if (current_time - current_node->last_checked >
|
||||||
|
@ -219,7 +219,8 @@ void Guardian_thread::run()
|
||||||
|
|
||||||
/* check the loop predicate before sleeping */
|
/* check the loop predicate before sleeping */
|
||||||
if (!(shutdown_requested && (!(guarded_instances))))
|
if (!(shutdown_requested && (!(guarded_instances))))
|
||||||
pthread_cond_timedwait(&COND_guardian, &LOCK_guardian, &timeout);
|
thread_registry.cond_timedwait(&thread_info, &COND_guardian,
|
||||||
|
&LOCK_guardian, &timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
stopped= TRUE;
|
stopped= TRUE;
|
||||||
|
@ -365,18 +366,20 @@ int Guardian_thread::stop_guard(Instance *instance)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Start Guardian shutdown. Attempt to start instances if requested.
|
An internal method which is called at shutdown to unregister instances and
|
||||||
|
attempt to stop them if requested.
|
||||||
|
|
||||||
SYNOPSYS
|
SYNOPSYS
|
||||||
stop_instances()
|
stop_instances()
|
||||||
stop_instances_arg whether we should stop instances at shutdown
|
stop_instances_arg whether we should stop instances at shutdown
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
|
|
||||||
Loops through the guarded_instances list and prepares them for shutdown.
|
Loops through the guarded_instances list and prepares them for shutdown.
|
||||||
If stop_instances was requested, we need to issue a stop command and change
|
If stop_instances was requested, we need to issue a stop command and change
|
||||||
the state accordingly. Otherwise we could simply delete an entry.
|
the state accordingly. Otherwise we simply delete an entry.
|
||||||
NOTE: Guardian should be locked by the calling function
|
|
||||||
|
NOTE
|
||||||
|
Guardian object should be locked by the calling function.
|
||||||
|
|
||||||
RETURN
|
RETURN
|
||||||
0 - ok
|
0 - ok
|
||||||
|
|
|
@ -62,8 +62,8 @@ class Guardian_thread: public Guardian_thread_args
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/* states of an instance */
|
/* states of an instance */
|
||||||
enum INSTANCE_STATE { NOT_STARTED= 1, STARTING, STARTED, JUST_CRASHED,
|
enum enum_instance_state { NOT_STARTED= 1, STARTING, STARTED, JUST_CRASHED,
|
||||||
CRASHED, CRASHED_AND_ABANDONED, STOPPING };
|
CRASHED, CRASHED_AND_ABANDONED, STOPPING };
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The Guardian list node structure. Guardian utilizes it to store
|
The Guardian list node structure. Guardian utilizes it to store
|
||||||
|
@ -74,7 +74,7 @@ public:
|
||||||
{
|
{
|
||||||
Instance *instance;
|
Instance *instance;
|
||||||
/* state of an instance (i.e. STARTED, CRASHED, etc.) */
|
/* state of an instance (i.e. STARTED, CRASHED, etc.) */
|
||||||
INSTANCE_STATE state;
|
enum_instance_state state;
|
||||||
/* the amount of attemts to restart instance (cleaned up at success) */
|
/* the amount of attemts to restart instance (cleaned up at success) */
|
||||||
int restart_counter;
|
int restart_counter;
|
||||||
/* triggered at a crash */
|
/* triggered at a crash */
|
||||||
|
|
|
@ -49,12 +49,12 @@ public:
|
||||||
Instance_options options;
|
Instance_options options;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
int crashed;
|
||||||
/*
|
/*
|
||||||
Mutex protecting the instance. Currently we use it to avoid the
|
Mutex protecting the instance. Currently we use it to avoid the
|
||||||
double start of the instance. This happens when the instance is starting
|
double start of the instance. This happens when the instance is starting
|
||||||
and we issue the start command once more.
|
and we issue the start command once more.
|
||||||
*/
|
*/
|
||||||
int crashed;
|
|
||||||
pthread_mutex_t LOCK_instance;
|
pthread_mutex_t LOCK_instance;
|
||||||
/*
|
/*
|
||||||
This condition variable is used to wake threads waiting for instance to
|
This condition variable is used to wake threads waiting for instance to
|
||||||
|
|
|
@ -91,22 +91,20 @@ static int process_option(void *ctx, const char *group, const char *option)
|
||||||
if ((instance= map->find(group, strlen(group))) == NULL)
|
if ((instance= map->find(group, strlen(group))) == NULL)
|
||||||
{
|
{
|
||||||
if ((instance= new Instance) == 0)
|
if ((instance= new Instance) == 0)
|
||||||
goto err_new_instance;
|
|
||||||
if (instance->init(group))
|
|
||||||
goto err;
|
|
||||||
if (map->add_instance(instance))
|
|
||||||
goto err;
|
goto err;
|
||||||
|
if (instance->init(group) || map->add_instance(instance))
|
||||||
|
goto err_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (instance->options.add_option(option))
|
if (instance->options.add_option(option))
|
||||||
goto err;
|
goto err; /* the instance'll be deleted when we destroy the map */
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err:
|
err_instance:
|
||||||
delete instance;
|
delete instance;
|
||||||
err_new_instance:
|
err:
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,10 +120,8 @@ mysqld_path(default_mysqld_path_arg)
|
||||||
|
|
||||||
int Instance_map::init()
|
int Instance_map::init()
|
||||||
{
|
{
|
||||||
if (hash_init(&hash, default_charset_info, START_HASH_SIZE, 0, 0,
|
return hash_init(&hash, default_charset_info, START_HASH_SIZE, 0, 0,
|
||||||
get_instance_key, delete_instance, 0))
|
get_instance_key, delete_instance, 0);
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Instance_map::~Instance_map()
|
Instance_map::~Instance_map()
|
||||||
|
@ -217,10 +213,9 @@ int Instance_map::complete_initialization()
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
err:
|
|
||||||
return 1;
|
|
||||||
err_instance:
|
err_instance:
|
||||||
delete instance;
|
delete instance;
|
||||||
|
err:
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,13 +51,9 @@ static inline int create_mysqld_command(Buffer *buf,
|
||||||
/* here the '\0' character is copied from the option string */
|
/* here the '\0' character is copied from the option string */
|
||||||
buf->append(position, option, option_len);
|
buf->append(position, option, option_len);
|
||||||
|
|
||||||
if (buf->is_error())
|
return buf->is_error();
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
else
|
return 1;
|
||||||
return 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -96,10 +92,8 @@ int Instance_options::get_default_option(char *result, size_t result_len,
|
||||||
/* +2 eats first "--" from the option string (E.g. "--datadir") */
|
/* +2 eats first "--" from the option string (E.g. "--datadir") */
|
||||||
rc= parse_output_and_get_value(cmd.buffer, option_name + 2,
|
rc= parse_output_and_get_value(cmd.buffer, option_name + 2,
|
||||||
result, result_len, GET_VALUE);
|
result, result_len, GET_VALUE);
|
||||||
|
|
||||||
return rc;
|
|
||||||
err:
|
err:
|
||||||
return 1;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -142,11 +136,8 @@ int Instance_options::fill_instance_version()
|
||||||
result[strlen(result) - NEWLINE_LEN]= '\0';
|
result[strlen(result) - NEWLINE_LEN]= '\0';
|
||||||
mysqld_version= strdup_root(&alloc, result);
|
mysqld_version= strdup_root(&alloc, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
err:
|
err:
|
||||||
return 1;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -194,13 +185,15 @@ int Instance_options::fill_log_options()
|
||||||
/* compute hostname and datadir for the instance */
|
/* compute hostname and datadir for the instance */
|
||||||
if (mysqld_datadir == NULL)
|
if (mysqld_datadir == NULL)
|
||||||
{
|
{
|
||||||
if (get_default_option(datadir,
|
if (get_default_option(datadir, MAX_LOG_OPTION_LENGTH, "--datadir"))
|
||||||
MAX_LOG_OPTION_LENGTH, "--datadir"))
|
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
else /* below is safe, as --datadir always has a value */
|
else
|
||||||
strmake(datadir, strchr(mysqld_datadir, '=') + 1,
|
{
|
||||||
MAX_LOG_OPTION_LENGTH - 1);
|
/* below is safe, as --datadir always has a value */
|
||||||
|
strmake(datadir,
|
||||||
|
strchr(mysqld_datadir, '=') + 1, MAX_LOG_OPTION_LENGTH - 1);
|
||||||
|
}
|
||||||
|
|
||||||
if (gethostname(hostname,sizeof(hostname)-1) < 0)
|
if (gethostname(hostname,sizeof(hostname)-1) < 0)
|
||||||
strmov(hostname, "mysql");
|
strmov(hostname, "mysql");
|
||||||
|
@ -230,15 +223,12 @@ int Instance_options::fill_log_options()
|
||||||
MY_UNPACK_FILENAME | MY_SAFE_PATH);
|
MY_UNPACK_FILENAME | MY_SAFE_PATH);
|
||||||
|
|
||||||
|
|
||||||
if ((MAX_LOG_OPTION_LENGTH - strlen(full_name)) >
|
if ((MAX_LOG_OPTION_LENGTH - strlen(full_name)) <=
|
||||||
strlen(log_files->default_suffix))
|
strlen(log_files->default_suffix))
|
||||||
{
|
|
||||||
strmov(full_name + strlen(full_name),
|
|
||||||
log_files->default_suffix);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
strmov(full_name + strlen(full_name), log_files->default_suffix);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
If there were specified two identical logfiles options,
|
If there were specified two identical logfiles options,
|
||||||
we would loose some memory in MEM_ROOT here. However
|
we would loose some memory in MEM_ROOT here. However
|
||||||
|
@ -254,8 +244,7 @@ int Instance_options::fill_log_options()
|
||||||
fn_format(full_name, argv[i] +log_files->length + 1,
|
fn_format(full_name, argv[i] +log_files->length + 1,
|
||||||
datadir, "", MY_UNPACK_FILENAME | MY_SAFE_PATH);
|
datadir, "", MY_UNPACK_FILENAME | MY_SAFE_PATH);
|
||||||
|
|
||||||
if (!(*(log_files->value)=
|
if (!(*(log_files->value)= strdup_root(&alloc, full_name)))
|
||||||
strdup_root(&alloc, full_name)))
|
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -263,10 +252,8 @@ int Instance_options::fill_log_options()
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -294,7 +281,7 @@ int Instance_options::get_pid_filename(char *result)
|
||||||
const char *pid_file= mysqld_pid_file;
|
const char *pid_file= mysqld_pid_file;
|
||||||
char datadir[MAX_PATH_LEN];
|
char datadir[MAX_PATH_LEN];
|
||||||
|
|
||||||
if (!(mysqld_datadir))
|
if (mysqld_datadir == NULL)
|
||||||
{
|
{
|
||||||
/* we might get an error here if we have wrong path to the mysqld binary */
|
/* we might get an error here if we have wrong path to the mysqld binary */
|
||||||
if (get_default_option(datadir, sizeof(datadir), "--datadir"))
|
if (get_default_option(datadir, sizeof(datadir), "--datadir"))
|
||||||
|
@ -333,8 +320,7 @@ pid_t Instance_options::get_pid()
|
||||||
my_fclose(pid_file_stream, MYF(0));
|
my_fclose(pid_file_stream, MYF(0));
|
||||||
return pid;
|
return pid;
|
||||||
}
|
}
|
||||||
else
|
return 0;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -343,11 +329,8 @@ int Instance_options::complete_initialization(const char *default_path,
|
||||||
{
|
{
|
||||||
const char *tmp;
|
const char *tmp;
|
||||||
|
|
||||||
if (!(mysqld_path))
|
if (!mysqld_path && !(mysqld_path= strdup_root(&alloc, default_path)))
|
||||||
{
|
goto err;
|
||||||
if (!(mysqld_path= strdup_root(&alloc, default_path)))
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
mysqld_path_len= strlen(mysqld_path);
|
mysqld_path_len= strlen(mysqld_path);
|
||||||
|
|
||||||
|
@ -395,9 +378,10 @@ int Instance_options::complete_initialization(const char *default_path,
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
/* we need to reserve space for the final zero + possible default options */
|
/* we need to reserve space for the final zero + possible default options */
|
||||||
if (!(argv= (char**) alloc_root(&alloc, (options_array.elements + 1
|
if (!(argv= (char**)
|
||||||
+ MAX_NUMBER_OF_DEFAULT_OPTIONS) * sizeof(char*))))
|
alloc_root(&alloc, (options_array.elements + 1
|
||||||
goto err;
|
+ MAX_NUMBER_OF_DEFAULT_OPTIONS) * sizeof(char*))))
|
||||||
|
goto err;
|
||||||
|
|
||||||
/* the path must be first in the argv */
|
/* the path must be first in the argv */
|
||||||
if (add_to_argv(mysqld_path))
|
if (add_to_argv(mysqld_path))
|
||||||
|
@ -465,8 +449,8 @@ int Instance_options::add_option(const char* option)
|
||||||
|
|
||||||
for (selected_options= options; selected_options->name; selected_options++)
|
for (selected_options= options; selected_options->name; selected_options++)
|
||||||
{
|
{
|
||||||
if (!strncmp(tmp, selected_options->name, selected_options->length))
|
if (strncmp(tmp, selected_options->name, selected_options->length) == 0)
|
||||||
switch(selected_options->type){
|
switch (selected_options->type) {
|
||||||
case SAVE_WHOLE_AND_ADD:
|
case SAVE_WHOLE_AND_ADD:
|
||||||
*(selected_options->value)= tmp;
|
*(selected_options->value)= tmp;
|
||||||
insert_dynamic(&options_array,(gptr) &tmp);
|
insert_dynamic(&options_array,(gptr) &tmp);
|
||||||
|
@ -496,7 +480,7 @@ int Instance_options::add_to_argv(const char* option)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(filled_default_options < MAX_NUMBER_OF_DEFAULT_OPTIONS);
|
DBUG_ASSERT(filled_default_options < MAX_NUMBER_OF_DEFAULT_OPTIONS);
|
||||||
|
|
||||||
if ((option))
|
if (option)
|
||||||
argv[filled_default_options++]= (char*) option;
|
argv[filled_default_options++]= (char*) option;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -508,9 +492,7 @@ void Instance_options::print_argv()
|
||||||
int i;
|
int i;
|
||||||
printf("printing out an instance %s argv:\n", instance_name);
|
printf("printing out an instance %s argv:\n", instance_name);
|
||||||
for (i=0; argv[i] != NULL; i++)
|
for (i=0; argv[i] != NULL; i++)
|
||||||
{
|
|
||||||
printf("argv: %s\n", argv[i]);
|
printf("argv: %s\n", argv[i]);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -526,10 +508,10 @@ int Instance_options::init(const char *instance_name_arg)
|
||||||
init_alloc_root(&alloc, MEM_ROOT_BLOCK_SIZE, 0);
|
init_alloc_root(&alloc, MEM_ROOT_BLOCK_SIZE, 0);
|
||||||
|
|
||||||
if (my_init_dynamic_array(&options_array, sizeof(char*), 0, 32))
|
if (my_init_dynamic_array(&options_array, sizeof(char*), 0, 32))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (!(instance_name= strmake_root(&alloc, (char*) instance_name_arg,
|
if (!(instance_name= strmake_root(&alloc, (char*) instance_name_arg,
|
||||||
instance_name_len)))
|
instance_name_len)))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -39,17 +39,14 @@ static int create_pid_file(const char *pid_file_name)
|
||||||
{
|
{
|
||||||
if (FILE *pid_file= my_fopen(pid_file_name,
|
if (FILE *pid_file= my_fopen(pid_file_name,
|
||||||
O_WRONLY | O_CREAT | O_BINARY, MYF(0)))
|
O_WRONLY | O_CREAT | O_BINARY, MYF(0)))
|
||||||
{
|
{
|
||||||
fprintf(pid_file, "%d\n", (int) getpid());
|
fprintf(pid_file, "%d\n", (int) getpid());
|
||||||
my_fclose(pid_file, MYF(0));
|
my_fclose(pid_file, MYF(0));
|
||||||
}
|
return 0;
|
||||||
else
|
}
|
||||||
{
|
log_error("can't create pid file %s: errno=%d, %s",
|
||||||
log_error("can't create pid file %s: errno=%d, %s",
|
pid_file_name, errno, strerror(errno));
|
||||||
pid_file_name, errno, strerror(errno));
|
return 1;
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef __WIN__
|
#ifndef __WIN__
|
||||||
|
@ -136,7 +133,7 @@ void manager(const Options &options)
|
||||||
instance_map.guardian= &guardian_thread;
|
instance_map.guardian= &guardian_thread;
|
||||||
|
|
||||||
if (instance_map.init() || user_map.init())
|
if (instance_map.init() || user_map.init())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
||||||
if (instance_map.load())
|
if (instance_map.load())
|
||||||
|
@ -145,7 +142,7 @@ void manager(const Options &options)
|
||||||
"the wrong config file options. For instance, missing mysqld "
|
"the wrong config file options. For instance, missing mysqld "
|
||||||
"binary. Aborting.");
|
"binary. Aborting.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user_map.load(options.password_file_name))
|
if (user_map.load(options.password_file_name))
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -29,7 +29,6 @@
|
||||||
#include "protocol.h"
|
#include "protocol.h"
|
||||||
#include "messages.h"
|
#include "messages.h"
|
||||||
#include "command.h"
|
#include "command.h"
|
||||||
#include "factory.h"
|
|
||||||
#include "parse.h"
|
#include "parse.h"
|
||||||
|
|
||||||
#include <mysql.h>
|
#include <mysql.h>
|
||||||
|
@ -39,8 +38,6 @@
|
||||||
#include <my_sys.h>
|
#include <my_sys.h>
|
||||||
|
|
||||||
|
|
||||||
Command *parse_command(Command_factory * factory, const char *text);
|
|
||||||
|
|
||||||
Mysql_connection_thread_args::Mysql_connection_thread_args(
|
Mysql_connection_thread_args::Mysql_connection_thread_args(
|
||||||
struct st_vio *vio_arg,
|
struct st_vio *vio_arg,
|
||||||
Thread_registry &thread_registry_arg,
|
Thread_registry &thread_registry_arg,
|
||||||
|
@ -336,8 +333,7 @@ int Mysql_connection_thread::dispatch_command(enum enum_server_command command,
|
||||||
{
|
{
|
||||||
log_info("query for connection %d : ----\n%s\n-------------------------",
|
log_info("query for connection %d : ----\n%s\n-------------------------",
|
||||||
connection_id,packet);
|
connection_id,packet);
|
||||||
Command_factory commands_factory(instance_map);
|
if (Command *command= parse_command(&instance_map, packet))
|
||||||
if (Command *command= parse_command(&commands_factory, packet))
|
|
||||||
{
|
{
|
||||||
int res= 0;
|
int res= 0;
|
||||||
log_info("query for connection %d successefully parsed",connection_id);
|
log_info("query for connection %d successefully parsed",connection_id);
|
||||||
|
|
|
@ -244,8 +244,6 @@ C_MODE_END
|
||||||
|
|
||||||
int Options::load(int argc, char **argv)
|
int Options::load(int argc, char **argv)
|
||||||
{
|
{
|
||||||
saved_argv= argv;
|
|
||||||
|
|
||||||
if (argc >= 2)
|
if (argc >= 2)
|
||||||
{
|
{
|
||||||
if (is_prefix(argv[1], "--defaults-file="))
|
if (is_prefix(argv[1], "--defaults-file="))
|
||||||
|
@ -267,6 +265,8 @@ int Options::load(int argc, char **argv)
|
||||||
if (setup_windows_defaults())
|
if (setup_windows_defaults())
|
||||||
goto err;
|
goto err;
|
||||||
#endif
|
#endif
|
||||||
|
/* load_defaults will reset saved_argv with a new allocated list */
|
||||||
|
saved_argv= argv;
|
||||||
|
|
||||||
/* config-file options are prepended to command-line ones */
|
/* config-file options are prepended to command-line ones */
|
||||||
load_defaults(config_file, default_groups, &argc,
|
load_defaults(config_file, default_groups, &argc,
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
|
|
||||||
#include "parse.h"
|
#include "parse.h"
|
||||||
#include "factory.h"
|
#include "commands.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ int get_text_id(const char **text, uint *word_len, const char **id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Command *parse_command(Command_factory *factory, const char *text)
|
Command *parse_command(Instance_map *map, const char *text)
|
||||||
{
|
{
|
||||||
uint word_len;
|
uint word_len;
|
||||||
const char *instance_name;
|
const char *instance_name;
|
||||||
|
@ -147,10 +147,10 @@ Command *parse_command(Command_factory *factory, const char *text)
|
||||||
if (word_len)
|
if (word_len)
|
||||||
goto syntax_error;
|
goto syntax_error;
|
||||||
|
|
||||||
command= (tok1 == TOK_START) ? (Command *)
|
if (tok1 == TOK_START)
|
||||||
factory->new_Start_instance(instance_name, instance_name_len):
|
command= new Start_instance(map, instance_name, instance_name_len);
|
||||||
(Command *)
|
else
|
||||||
factory->new_Stop_instance(instance_name, instance_name_len);
|
command= new Stop_instance(map, instance_name, instance_name_len);
|
||||||
break;
|
break;
|
||||||
case TOK_FLUSH:
|
case TOK_FLUSH:
|
||||||
if (shift_token(&text, &word_len) != TOK_INSTANCES)
|
if (shift_token(&text, &word_len) != TOK_INSTANCES)
|
||||||
|
@ -160,7 +160,7 @@ Command *parse_command(Command_factory *factory, const char *text)
|
||||||
if (word_len)
|
if (word_len)
|
||||||
goto syntax_error;
|
goto syntax_error;
|
||||||
|
|
||||||
command= factory->new_Flush_instances();
|
command= new Flush_instances(map);
|
||||||
break;
|
break;
|
||||||
case TOK_UNSET:
|
case TOK_UNSET:
|
||||||
skip= true;
|
skip= true;
|
||||||
|
@ -201,13 +201,13 @@ Command *parse_command(Command_factory *factory, const char *text)
|
||||||
goto syntax_error;
|
goto syntax_error;
|
||||||
|
|
||||||
if (skip)
|
if (skip)
|
||||||
command= factory->new_Unset_option(instance_name, instance_name_len,
|
command= new Unset_option(map, instance_name, instance_name_len,
|
||||||
option, option_len, option_value,
|
option, option_len, option_value,
|
||||||
option_value_len);
|
option_value_len);
|
||||||
else
|
else
|
||||||
command= factory->new_Set_option(instance_name, instance_name_len,
|
command= new Set_option(map, instance_name, instance_name_len,
|
||||||
option, option_len, option_value,
|
option, option_len, option_value,
|
||||||
option_value_len);
|
option_value_len);
|
||||||
break;
|
break;
|
||||||
case TOK_SHOW:
|
case TOK_SHOW:
|
||||||
switch (shift_token(&text, &word_len)) {
|
switch (shift_token(&text, &word_len)) {
|
||||||
|
@ -215,7 +215,7 @@ Command *parse_command(Command_factory *factory, const char *text)
|
||||||
get_word(&text, &word_len);
|
get_word(&text, &word_len);
|
||||||
if (word_len)
|
if (word_len)
|
||||||
goto syntax_error;
|
goto syntax_error;
|
||||||
command= factory->new_Show_instances();
|
command= new Show_instances(map);
|
||||||
break;
|
break;
|
||||||
case TOK_INSTANCE:
|
case TOK_INSTANCE:
|
||||||
switch (Token tok2= shift_token(&text, &word_len)) {
|
switch (Token tok2= shift_token(&text, &word_len)) {
|
||||||
|
@ -227,12 +227,12 @@ Command *parse_command(Command_factory *factory, const char *text)
|
||||||
get_word(&text, &word_len);
|
get_word(&text, &word_len);
|
||||||
if (word_len)
|
if (word_len)
|
||||||
goto syntax_error;
|
goto syntax_error;
|
||||||
command= (tok2 == TOK_STATUS) ? (Command *)
|
if (tok2 == TOK_STATUS)
|
||||||
factory->new_Show_instance_status(instance_name,
|
command= new Show_instance_status(map, instance_name,
|
||||||
instance_name_len):
|
instance_name_len);
|
||||||
(Command *)
|
else
|
||||||
factory->new_Show_instance_options(instance_name,
|
command= new Show_instance_options(map, instance_name,
|
||||||
instance_name_len);
|
instance_name_len);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
goto syntax_error;
|
goto syntax_error;
|
||||||
|
@ -252,9 +252,8 @@ Command *parse_command(Command_factory *factory, const char *text)
|
||||||
/* check that this is the end of the command */
|
/* check that this is the end of the command */
|
||||||
if (word_len)
|
if (word_len)
|
||||||
goto syntax_error;
|
goto syntax_error;
|
||||||
command= (Command *)
|
command= new Show_instance_log_files(map, instance_name,
|
||||||
factory->new_Show_instance_log_files(instance_name,
|
instance_name_len);
|
||||||
instance_name_len);
|
|
||||||
break;
|
break;
|
||||||
case TOK_ERROR:
|
case TOK_ERROR:
|
||||||
case TOK_GENERAL:
|
case TOK_GENERAL:
|
||||||
|
@ -288,22 +287,16 @@ Command *parse_command(Command_factory *factory, const char *text)
|
||||||
get_word(&text, &word_len);
|
get_word(&text, &word_len);
|
||||||
if (!word_len)
|
if (!word_len)
|
||||||
goto syntax_error;
|
goto syntax_error;
|
||||||
command= (Command *)
|
command= new Show_instance_log(map, instance_name,
|
||||||
factory->new_Show_instance_log(instance_name,
|
instance_name_len, log_type,
|
||||||
instance_name_len,
|
log_size, text);
|
||||||
log_type,
|
|
||||||
log_size,
|
|
||||||
text);
|
|
||||||
|
|
||||||
//get_text_id(&text, &log_size_len, &log_size);
|
//get_text_id(&text, &log_size_len, &log_size);
|
||||||
break;
|
break;
|
||||||
case '\0':
|
case '\0':
|
||||||
command= (Command *)
|
command= new Show_instance_log(map, instance_name,
|
||||||
factory->new_Show_instance_log(instance_name,
|
instance_name_len, log_type,
|
||||||
instance_name_len,
|
log_size, NULL);
|
||||||
log_type,
|
|
||||||
log_size,
|
|
||||||
NULL);
|
|
||||||
break; /* this is ok */
|
break; /* this is ok */
|
||||||
default:
|
default:
|
||||||
goto syntax_error;
|
goto syntax_error;
|
||||||
|
@ -324,7 +317,7 @@ Command *parse_command(Command_factory *factory, const char *text)
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
syntax_error:
|
syntax_error:
|
||||||
command= factory->new_Syntax_error();
|
command= new Syntax_error();
|
||||||
}
|
}
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#include <my_sys.h>
|
#include <my_sys.h>
|
||||||
|
|
||||||
class Command;
|
class Command;
|
||||||
class Command_factory;
|
class Instance_map;
|
||||||
|
|
||||||
enum Log_type
|
enum Log_type
|
||||||
{
|
{
|
||||||
|
@ -29,7 +29,7 @@ enum Log_type
|
||||||
IM_LOG_SLOW
|
IM_LOG_SLOW
|
||||||
};
|
};
|
||||||
|
|
||||||
Command *parse_command(Command_factory *factory, const char *text);
|
Command *parse_command(Instance_map *instance_map, const char *text);
|
||||||
|
|
||||||
/* define kinds of the word seek method */
|
/* define kinds of the word seek method */
|
||||||
enum { ALPHANUM= 1, NONSPACE };
|
enum { ALPHANUM= 1, NONSPACE };
|
||||||
|
@ -62,5 +62,4 @@ inline void get_word(const char **text, uint *word_len,
|
||||||
*word_len= word_end - *text;
|
*word_len= word_end - *text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_PARSE_H */
|
#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_PARSE_H */
|
||||||
|
|
|
@ -43,8 +43,8 @@
|
||||||
if flag is GET_VALUE. Return the rest of the parsed string otherwise.
|
if flag is GET_VALUE. Return the rest of the parsed string otherwise.
|
||||||
|
|
||||||
RETURN
|
RETURN
|
||||||
0 - ok
|
0 - ok, the word has been found
|
||||||
1 - error occured
|
1 - error occured or the word is not found
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int parse_output_and_get_value(const char *command, const char *word,
|
int parse_output_and_get_value(const char *command, const char *word,
|
||||||
|
@ -56,9 +56,15 @@ int parse_output_and_get_value(const char *command, const char *word,
|
||||||
/* should be enough to store the string from the output */
|
/* should be enough to store the string from the output */
|
||||||
enum { MAX_LINE_LEN= 512 };
|
enum { MAX_LINE_LEN= 512 };
|
||||||
char linebuf[MAX_LINE_LEN];
|
char linebuf[MAX_LINE_LEN];
|
||||||
|
int rc= 1;
|
||||||
|
|
||||||
wordlen= strlen(word);
|
wordlen= strlen(word);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Successful return of popen does not tell us whether the command has been
|
||||||
|
executed successfully: if the command was not found, we'll get EOF
|
||||||
|
when reading the output buffer below.
|
||||||
|
*/
|
||||||
if (!(output= popen(command, "r")))
|
if (!(output= popen(command, "r")))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
@ -95,10 +101,9 @@ int parse_output_and_get_value(const char *command, const char *word,
|
||||||
strmake(result, linep, found_word_len);
|
strmake(result, linep, found_word_len);
|
||||||
}
|
}
|
||||||
else /* currently there are only two options */
|
else /* currently there are only two options */
|
||||||
{
|
|
||||||
strmake(result, linep, input_buffer_len - 1);
|
strmake(result, linep, input_buffer_len - 1);
|
||||||
}
|
rc= 0;
|
||||||
goto pclose;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,9 +111,7 @@ pclose:
|
||||||
/* we are not interested in the termination status */
|
/* we are not interested in the termination status */
|
||||||
pclose(output);
|
pclose(output);
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
err:
|
err:
|
||||||
return 1;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
#define SIGKILL 9
|
#define SIGKILL 9
|
||||||
#define SHUT_RDWR 0x2
|
#define SHUT_RDWR 0x2
|
||||||
|
|
||||||
//TODO: fix this
|
/*TODO: fix this */
|
||||||
#define DEFAULT_MONITORING_INTERVAL 20
|
#define DEFAULT_MONITORING_INTERVAL 20
|
||||||
#define DEFAULT_PORT 2273
|
#define DEFAULT_PORT 2273
|
||||||
#define PROTOCOL_VERSION 10
|
#define PROTOCOL_VERSION 10
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 2003 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
|
/* cOPYRIght (C) 2003 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -122,11 +122,10 @@ void Thread_registry::unregister_thread(Thread_info *info)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int Thread_registry::cond_wait(Thread_info *info, pthread_cond_t *cond,
|
int Thread_registry::cond_wait(Thread_info *info, pthread_cond_t *cond,
|
||||||
pthread_mutex_t *mutex, bool *is_shutdown)
|
pthread_mutex_t *mutex)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&LOCK_thread_registry);
|
pthread_mutex_lock(&LOCK_thread_registry);
|
||||||
*is_shutdown= shutdown_in_progress;
|
if (shutdown_in_progress)
|
||||||
if (*is_shutdown)
|
|
||||||
{
|
{
|
||||||
pthread_mutex_unlock(&LOCK_thread_registry);
|
pthread_mutex_unlock(&LOCK_thread_registry);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -137,7 +136,27 @@ int Thread_registry::cond_wait(Thread_info *info, pthread_cond_t *cond,
|
||||||
int rc= pthread_cond_wait(cond, mutex);
|
int rc= pthread_cond_wait(cond, mutex);
|
||||||
pthread_mutex_lock(&LOCK_thread_registry);
|
pthread_mutex_lock(&LOCK_thread_registry);
|
||||||
info->current_cond= 0;
|
info->current_cond= 0;
|
||||||
*is_shutdown= shutdown_in_progress;
|
pthread_mutex_unlock(&LOCK_thread_registry);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int Thread_registry::cond_timedwait(Thread_info *info, pthread_cond_t *cond,
|
||||||
|
pthread_mutex_t *mutex,
|
||||||
|
struct timespec *wait_time)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&LOCK_thread_registry);
|
||||||
|
if (shutdown_in_progress)
|
||||||
|
{
|
||||||
|
pthread_mutex_unlock(&LOCK_thread_registry);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
info->current_cond= cond;
|
||||||
|
pthread_mutex_unlock(&LOCK_thread_registry);
|
||||||
|
/* sic: race condition here, cond can be signaled in deliver_shutdown */
|
||||||
|
int rc= pthread_cond_timedwait(cond, mutex, wait_time);
|
||||||
|
pthread_mutex_lock(&LOCK_thread_registry);
|
||||||
|
info->current_cond= 0;
|
||||||
pthread_mutex_unlock(&LOCK_thread_registry);
|
pthread_mutex_unlock(&LOCK_thread_registry);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
stop all running threads, cleanup and exit.
|
stop all running threads, cleanup and exit.
|
||||||
|
|
||||||
Note, that a thread can't be shut down nicely if it doesn't want to be.
|
Note, that a thread can't be shut down nicely if it doesn't want to be.
|
||||||
That's why to perform clean shutdown, all threads consituting a process
|
That's why to perform clean shutdown, all threads constituting a process
|
||||||
must observe certain rules. Here we use the rules, described in Butenhof
|
must observe certain rules. Here we use the rules, described in Butenhof
|
||||||
book 'Programming with POSIX threads', namely:
|
book 'Programming with POSIX threads', namely:
|
||||||
- all user signals are handled in 'signal thread' in synchronous manner
|
- all user signals are handled in 'signal thread' in synchronous manner
|
||||||
|
@ -94,7 +94,9 @@ public:
|
||||||
void request_shutdown();
|
void request_shutdown();
|
||||||
inline bool is_shutdown();
|
inline bool is_shutdown();
|
||||||
int cond_wait(Thread_info *info, pthread_cond_t *cond,
|
int cond_wait(Thread_info *info, pthread_cond_t *cond,
|
||||||
pthread_mutex_t *mutex, bool *is_shutdown);
|
pthread_mutex_t *mutex);
|
||||||
|
int cond_timedwait(Thread_info *info, pthread_cond_t *cond,
|
||||||
|
pthread_mutex_t *mutex, struct timespec *wait_time);
|
||||||
private:
|
private:
|
||||||
Thread_info head;
|
Thread_info head;
|
||||||
bool shutdown_in_progress;
|
bool shutdown_in_progress;
|
||||||
|
|
|
@ -128,7 +128,7 @@ int User_map::load(const char *password_file_name)
|
||||||
char line[USERNAME_LENGTH + SCRAMBLED_PASSWORD_CHAR_LENGTH +
|
char line[USERNAME_LENGTH + SCRAMBLED_PASSWORD_CHAR_LENGTH +
|
||||||
2 + /* for possible quotes */
|
2 + /* for possible quotes */
|
||||||
1 + /* for ':' */
|
1 + /* for ':' */
|
||||||
1 + /* for newline */
|
2 + /* for newline */
|
||||||
1]; /* for trailing zero */
|
1]; /* for trailing zero */
|
||||||
User *user;
|
User *user;
|
||||||
int rc= 1;
|
int rc= 1;
|
||||||
|
|
|
@ -734,11 +734,13 @@ longlong Item_func_numhybrid::val_int()
|
||||||
case STRING_RESULT:
|
case STRING_RESULT:
|
||||||
{
|
{
|
||||||
int err_not_used;
|
int err_not_used;
|
||||||
String *res= str_op(&str_value);
|
String *res;
|
||||||
|
if (!(res= str_op(&str_value)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
char *end= (char*) res->ptr() + res->length();
|
char *end= (char*) res->ptr() + res->length();
|
||||||
CHARSET_INFO *cs= str_value.charset();
|
CHARSET_INFO *cs= str_value.charset();
|
||||||
return (res ? (*(cs->cset->strtoll10))(cs, res->ptr(), &end,
|
return (*(cs->cset->strtoll10))(cs, res->ptr(), &end, &err_not_used);
|
||||||
&err_not_used) : 0);
|
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
DBUG_ASSERT(0);
|
DBUG_ASSERT(0);
|
||||||
|
@ -769,7 +771,10 @@ my_decimal *Item_func_numhybrid::val_decimal(my_decimal *decimal_value)
|
||||||
}
|
}
|
||||||
case STRING_RESULT:
|
case STRING_RESULT:
|
||||||
{
|
{
|
||||||
String *res= str_op(&str_value);
|
String *res;
|
||||||
|
if (!(res= str_op(&str_value)))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
str2my_decimal(E_DEC_FATAL_ERROR, (char*) res->ptr(),
|
str2my_decimal(E_DEC_FATAL_ERROR, (char*) res->ptr(),
|
||||||
res->length(), res->charset(), decimal_value);
|
res->length(), res->charset(), decimal_value);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -2820,15 +2820,15 @@ mysql_discard_or_import_tablespace(THD *thd,
|
||||||
err:
|
err:
|
||||||
close_thread_tables(thd);
|
close_thread_tables(thd);
|
||||||
thd->tablespace_op=FALSE;
|
thd->tablespace_op=FALSE;
|
||||||
|
|
||||||
if (error == 0)
|
if (error == 0)
|
||||||
{
|
{
|
||||||
send_ok(thd);
|
send_ok(thd);
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error == HA_ERR_ROW_IS_REFERENCED)
|
table->file->print_error(error, MYF(0));
|
||||||
my_error(ER_ROW_IS_REFERENCED, MYF(0));
|
|
||||||
|
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1020,11 +1020,19 @@ execute_var_ident: '@' ident_or_text
|
||||||
/* help */
|
/* help */
|
||||||
|
|
||||||
help:
|
help:
|
||||||
HELP_SYM ident_or_text
|
HELP_SYM
|
||||||
|
{
|
||||||
|
if (Lex->sphead)
|
||||||
|
{
|
||||||
|
my_error(ER_SP_BADSTATEMENT, MYF(0), "HELP");
|
||||||
|
YYABORT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ident_or_text
|
||||||
{
|
{
|
||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
lex->sql_command= SQLCOM_HELP;
|
lex->sql_command= SQLCOM_HELP;
|
||||||
lex->help_arg= $2.str;
|
lex->help_arg= $3.str;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* change master */
|
/* change master */
|
||||||
|
|
Loading…
Reference in a new issue