Commit 0b60b3fe authored by unknown's avatar unknown

Merge rurik.mysql.com:/home/igor/mysql-4.0

into rurik.mysql.com:/home/igor/dev/mysql-4.0-0
parents c0717b74 79632793
...@@ -545,3 +545,4 @@ vio/test-sslserver ...@@ -545,3 +545,4 @@ vio/test-sslserver
vio/viotest-ssl vio/viotest-ssl
scripts/make_win_binary_distribution scripts/make_win_binary_distribution
EXCEPTIONS-CLIENT EXCEPTIONS-CLIENT
support-files/my-innodb-heavy-4G.cnf
...@@ -2200,8 +2200,9 @@ static int com_source(String *buffer, char *line) ...@@ -2200,8 +2200,9 @@ static int com_source(String *buffer, char *line)
static int static int
com_use(String *buffer __attribute__((unused)), char *line) com_use(String *buffer __attribute__((unused)), char *line)
{ {
char *tmp; char *tmp, buff[FN_REFLEN + 1];
char buff[256]; MYSQL_RES *res;
MYSQL_ROW row;
while (isspace(*line)) while (isspace(*line))
line++; line++;
...@@ -2214,6 +2215,30 @@ com_use(String *buffer __attribute__((unused)), char *line) ...@@ -2214,6 +2215,30 @@ com_use(String *buffer __attribute__((unused)), char *line)
put_info("USE must be followed by a database name",INFO_ERROR); put_info("USE must be followed by a database name",INFO_ERROR);
return 0; return 0;
} }
/*
We need to recheck the current database, because it may change
under our feet, for example if DROP DATABASE or RENAME DATABASE
(latter one not yet available by the time the comment was written)
*/
/* Let's reset current_db, assume it's gone */
my_free(current_db, MYF(MY_ALLOW_ZERO_PTR));
current_db= 0;
/*
We don't care about in case of an error below because current_db
was just set to 0.
*/
if (!mysql_query(&mysql, "SELECT DATABASE()") &&
(res= mysql_use_result(&mysql)))
{
row= mysql_fetch_row(res);
if (row[0])
{
current_db= my_strdup(row[0], MYF(MY_WME));
}
(void) mysql_fetch_row(res); // Read eof
mysql_free_result(res);
}
if (!current_db || cmp_database(current_db,tmp)) if (!current_db || cmp_database(current_db,tmp))
{ {
if (one_database) if (one_database)
......
...@@ -413,18 +413,18 @@ static int process_all_tables_in_db(char *database) ...@@ -413,18 +413,18 @@ static int process_all_tables_in_db(char *database)
LINT_INIT(res); LINT_INIT(res);
if (use_db(database)) if (use_db(database))
return 1; return 1;
if (!(mysql_query(sock, "SHOW TABLES") || if (mysql_query(sock, "SHOW TABLES") ||
(res = mysql_store_result(sock)))) !((res= mysql_store_result(sock))))
return 1; return 1;
if (opt_all_in_1) if (opt_all_in_1)
{ {
/* /*
We need table list in form `a`, `b`, `c` We need table list in form `a`, `b`, `c`
that's why we need 4 more chars added to to each table name that's why we need 4 more chars added to to each table name
space is for more readable output in logs and in case of error space is for more readable output in logs and in case of error
*/ */
char *tables, *end; char *tables, *end;
uint tot_length = 0; uint tot_length = 0;
......
...@@ -34,14 +34,17 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking) ...@@ -34,14 +34,17 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking)
{ {
int save_errno,errpos=0; int save_errno,errpos=0;
uint files=0,i,dir_length,length,key_parts; uint files=0,i,dir_length,length,key_parts;
ulonglong file_offset; ulonglong file_offset=0;
char name_buff[FN_REFLEN*2],buff[FN_REFLEN],*end; char name_buff[FN_REFLEN*2],buff[FN_REFLEN],*end;
MYRG_INFO *m_info=0; MYRG_INFO *m_info=0;
File fd; File fd;
IO_CACHE file; IO_CACHE file;
MI_INFO *isam=0; MI_INFO *isam=0;
uint found_merge_insert_method= 0;
DBUG_ENTER("myrg_open"); DBUG_ENTER("myrg_open");
LINT_INIT(key_parts);
bzero((char*) &file,sizeof(file)); bzero((char*) &file,sizeof(file));
if ((fd=my_open(fn_format(name_buff,name,"",MYRG_NAME_EXT,4), if ((fd=my_open(fn_format(name_buff,name,"",MYRG_NAME_EXT,4),
O_RDONLY | O_SHARE,MYF(0))) < 0) O_RDONLY | O_SHARE,MYF(0))) < 0)
...@@ -69,10 +72,10 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking) ...@@ -69,10 +72,10 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking)
continue; /* Skip empty lines */ continue; /* Skip empty lines */
if (buff[0] == '#') if (buff[0] == '#')
{ {
if( !strncmp(buff+1,"INSERT_METHOD=",14)) if (!strncmp(buff+1,"INSERT_METHOD=",14))
{ /* Lookup insert method */ { /* Lookup insert method */
int tmp=find_type(buff+15,&merge_insert_method,2); int tmp=find_type(buff+15,&merge_insert_method,2);
m_info->merge_insert_method = (uint) (tmp >= 0 ? tmp : 0); found_merge_insert_method = (uint) (tmp >= 0 ? tmp : 0);
} }
continue; /* Skip comments */ continue; /* Skip comments */
} }
...@@ -84,8 +87,8 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking) ...@@ -84,8 +87,8 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking)
VOID(cleanup_dirname(buff,name_buff)); VOID(cleanup_dirname(buff,name_buff));
} }
if (!(isam=mi_open(buff,mode,(handle_locking?HA_OPEN_WAIT_IF_LOCKED:0)))) if (!(isam=mi_open(buff,mode,(handle_locking?HA_OPEN_WAIT_IF_LOCKED:0))))
goto err; goto err;
if (!m_info) if (!m_info) /* First file */
{ {
key_parts=isam->s->base.key_parts; key_parts=isam->s->base.key_parts;
if (!(m_info= (MYRG_INFO*) my_malloc(sizeof(MYRG_INFO) + if (!(m_info= (MYRG_INFO*) my_malloc(sizeof(MYRG_INFO) +
...@@ -97,15 +100,10 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking) ...@@ -97,15 +100,10 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking)
{ {
m_info->open_tables=(MYRG_TABLE *) (m_info+1); m_info->open_tables=(MYRG_TABLE *) (m_info+1);
m_info->rec_per_key_part=(ulong *) (m_info->open_tables+files); m_info->rec_per_key_part=(ulong *) (m_info->open_tables+files);
m_info->tables= files;
files= 0;
} }
else
{
m_info->open_tables=0;
m_info->rec_per_key_part=0;
}
m_info->tables=files;
m_info->reclength=isam->s->base.reclength; m_info->reclength=isam->s->base.reclength;
file_offset=files=0;
errpos=3; errpos=3;
} }
m_info->open_tables[files].table= isam; m_info->open_tables[files].table= isam;
...@@ -122,14 +120,16 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking) ...@@ -122,14 +120,16 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking)
m_info->del+= isam->state->del; m_info->del+= isam->state->del;
m_info->data_file_length+= isam->state->data_file_length; m_info->data_file_length+= isam->state->data_file_length;
for (i=0; i < key_parts; i++) for (i=0; i < key_parts; i++)
m_info->rec_per_key_part[i]+=isam->s->state.rec_per_key_part[i] / m_info->tables; m_info->rec_per_key_part[i]+= (isam->s->state.rec_per_key_part[i] /
m_info->tables);
} }
if (!m_info && !(m_info= (MYRG_INFO*) my_malloc(sizeof(MYRG_INFO), if (!m_info && !(m_info= (MYRG_INFO*) my_malloc(sizeof(MYRG_INFO),
MYF(MY_WME|MY_ZEROFILL)))) MYF(MY_WME | MY_ZEROFILL))))
goto err; goto err;
/* Don't mark table readonly, for ALTER TABLE ... UNION=(...) to work */ /* Don't mark table readonly, for ALTER TABLE ... UNION=(...) to work */
m_info->options&= ~(HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA); m_info->options&= ~(HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA);
m_info->merge_insert_method= found_merge_insert_method;
if (sizeof(my_off_t) == 4 && file_offset > (ulonglong) (ulong) ~0L) if (sizeof(my_off_t) == 4 && file_offset > (ulonglong) (ulong) ~0L)
{ {
......
slave stop;
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;
slave start;
drop database if exists mysqltest1;
create database mysqltest1 /*!40100 character set latin2 */;
use mysqltest1;
drop table if exists t1;
create table t1 (a varchar(255) character set latin2, b varchar(4));
SET CHARACTER SET cp1250_latin2;
INSERT INTO t1 VALUES ('','80');
INSERT INTO t1 VALUES ('','90');
INSERT INTO t1 VALUES ('','A0');
INSERT INTO t1 VALUES ('','B0');
INSERT INTO t1 VALUES ('','C0');
INSERT INTO t1 VALUES ('','D0');
INSERT INTO t1 VALUES ('','E0');
INSERT INTO t1 VALUES ('','F0');
select "--- on master ---";
--- on master ---
--- on master ---
select hex(a),b from t1 order by b;
hex(a) b
A9A6ABAEAC 80
B9B6BBBEBC 90
A3A1AAAF A0
B3B1BAA5B5BF B0
C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF C0
D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF D0
E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF E0
F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF F0
show binlog events from 1979;
Log_name Pos Event_type Server_id Orig_log_pos Info
master-bin.001 1979 Query 1 1979 use `mysqltest1`; SET CHARACTER SET DEFAULT
use mysqltest1;
select "--- on slave ---";
--- on slave ---
--- on slave ---
select hex(a),b from t1 order by b;
hex(a) b
A9A6ABAEAC 80
B9B6BBBEBC 90
A3A1AAAF A0
B3B1BAA5B5BF B0
C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF C0
D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF D0
E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF E0
F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF F0
drop database mysqltest1;
...@@ -88,7 +88,6 @@ explain (select a,b from t1 limit 2) union all (select a,b from t2 order by a l ...@@ -88,7 +88,6 @@ explain (select a,b from t1 limit 2) union all (select a,b from t2 order by a l
table type possible_keys key key_len ref rows Extra table type possible_keys key key_len ref rows Extra
t1 ALL NULL NULL NULL NULL 4 t1 ALL NULL NULL NULL NULL 4
t2 ALL NULL NULL NULL NULL 4 Using filesort t2 ALL NULL NULL NULL NULL 4 Using filesort
t1 ALL NULL NULL NULL NULL 4
(select sql_calc_found_rows a,b from t1 limit 2) union all (select a,b from t2 order by a) limit 2; (select sql_calc_found_rows a,b from t1 limit 2) union all (select a,b from t2 order by a) limit 2;
a b a b
1 a 1 a
...@@ -420,6 +419,7 @@ a ...@@ -420,6 +419,7 @@ a
(SELECT * FROM t1) UNION all (SELECT SQL_CALC_FOUND_ROWS * FROM t2) LIMIT 1; (SELECT * FROM t1) UNION all (SELECT SQL_CALC_FOUND_ROWS * FROM t2) LIMIT 1;
Wrong usage/placement of 'SQL_CALC_FOUND_ROWS' Wrong usage/placement of 'SQL_CALC_FOUND_ROWS'
create temporary table t1 select a from t1 union select a from t2; create temporary table t1 select a from t1 union select a from t2;
drop table t1;
create table t1 select a from t1 union select a from t2; create table t1 select a from t1 union select a from t2;
INSERT TABLE 't1' isn't allowed in FROM table list INSERT TABLE 't1' isn't allowed in FROM table list
select a from t1 union select a from t2 order by t2.a; select a from t1 union select a from t2 order by t2.a;
...@@ -429,3 +429,10 @@ select length(version()) > 1 as `*` UNION select 2; ...@@ -429,3 +429,10 @@ select length(version()) > 1 as `*` UNION select 2;
* *
1 1
2 2
create table t1 (a int);
insert into t1 values (0), (3), (1), (2);
explain (select * from t1) union (select * from t1) order by a;
table type possible_keys key key_len ref rows Extra
t1 ALL NULL NULL NULL NULL 4
t1 ALL NULL NULL NULL NULL 4
drop table t1;
source include/master-slave.inc;
--disable_warnings
drop database if exists mysqltest1;
# 4.1 bases its conversion on the db's charset,
# while 4.0 uses the part of "SET CHARACTER SET" after "_".
# So for 4.1 we add a clause to CREATE DATABASE.
create database mysqltest1 /*!40100 character set latin2 */;
use mysqltest1;
drop table if exists t1;
--enable_warnings
create table t1 (a varchar(255) character set latin2, b varchar(4));
SET CHARACTER SET cp1250_latin2;
INSERT INTO t1 VALUES ('ŠŒŽ','80');
INSERT INTO t1 VALUES ('šœžŸ','90');
INSERT INTO t1 VALUES ('£¥ª¯','A0');
INSERT INTO t1 VALUES ('³¹º¼¾¿','B0');
INSERT INTO t1 VALUES ('ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ','C0');
INSERT INTO t1 VALUES ('ÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞß','D0');
INSERT INTO t1 VALUES ('àáâãäåæçèéêëìíîï','E0');
INSERT INTO t1 VALUES ('ðñòóôõö÷øùúûüýþÿ','F0');
select "--- on master ---";
select hex(a),b from t1 order by b;
# It's complicated to verify that the charset is reset to default in
# the binlog after each query, except by checking the binlog. When you
# merge this into 4.1/5.0, the 1979 will have to be changed; all you have
# to do is read the var/log/master-bin.0*01 with mysqlbinlog, verify
# that a SET CHARACTER SET DEFAULT is just after the last INSERT, and
# replace 1979 by its position (the "# at" line above the SET).
show binlog events from 1979;
save_master_pos;
connection slave;
sync_with_master;
use mysqltest1;
select "--- on slave ---";
select hex(a),b from t1 order by b;
connection master;
drop database mysqltest1;
save_master_pos;
connection slave;
sync_with_master;
...@@ -224,6 +224,7 @@ SELECT * FROM t1 UNION SELECT * FROM t2 ORDER BY a desc LIMIT 1; ...@@ -224,6 +224,7 @@ SELECT * FROM t1 UNION SELECT * FROM t2 ORDER BY a desc LIMIT 1;
(SELECT * FROM t1) UNION all (SELECT SQL_CALC_FOUND_ROWS * FROM t2) LIMIT 1; (SELECT * FROM t1) UNION all (SELECT SQL_CALC_FOUND_ROWS * FROM t2) LIMIT 1;
create temporary table t1 select a from t1 union select a from t2; create temporary table t1 select a from t1 union select a from t2;
drop table t1;
--error 1093 --error 1093
create table t1 select a from t1 union select a from t2; create table t1 select a from t1 union select a from t2;
--error 1054 --error 1054
...@@ -236,3 +237,11 @@ drop table t1,t2; ...@@ -236,3 +237,11 @@ drop table t1,t2;
select length(version()) > 1 as `*` UNION select 2; select length(version()) > 1 as `*` UNION select 2;
#
# Bug #4980: problem with explain
#
create table t1 (a int);
insert into t1 values (0), (3), (1), (2);
explain (select * from t1) union (select * from t1) order by a;
drop table t1;
...@@ -322,36 +322,26 @@ do ...@@ -322,36 +322,26 @@ do
# but should work for the rest of the servers. # but should work for the rest of the servers.
# The only thing is ps x => redhat 5 gives warnings when using ps -x. # The only thing is ps x => redhat 5 gives warnings when using ps -x.
# kill -9 is used or the process won't react on the kill. # kill -9 is used or the process won't react on the kill.
if test -n "$mysql_tcp_port" numofproces=`ps xa | grep -v "grep" | grep "$ledir/$MYSQLD\>" | grep -c "pid-file=$pid_file"`
then
numofproces=`ps xa | grep -v "grep" | grep $ledir/$MYSQLD| grep -c "port=$mysql_tcp_port"`
else
numofproces=`ps xa | grep -v "grep" | grep -c $ledir/$MYSQLD`
fi
echo -e "\nNumber of processes running now: $numofproces" | tee -a $err_log echo -e "\nNumber of processes running now: $numofproces" | tee -a $err_log
I=1 I=1
while test "$I" -le "$numofproces" while test "$I" -le "$numofproces"
do do
if test -n "$mysql_tcp_port" PROC=`ps xa | grep "$ledir/$MYSQLD\>" | grep -v "grep" | grep "pid-file=$pid_file" | sed -n '$p'`
for T in $PROC
do
break
done
# echo "TEST $I - $T **"
if kill -9 $T
then then
PROC=`ps xa | grep "$ledir/$MYSQLD\>" | grep -v "grep" | grep "port=$mysql_tcp_port" | sed -n '$p'` echo "$MYSQLD process hanging, pid $T - killed" | tee -a $err_log
else else
PROC=`ps xa | grep "$ledir/$MYSQLD\>" | grep -v "grep" | sed -n '$p'` break
fi fi
I=`expr $I + 1`
for T in $PROC
do
break
done
# echo "TEST $I - $T **"
if kill -9 $T
then
echo "$MYSQLD process hanging, pid $T - killed" | tee -a $err_log
else
break
fi
I=`expr $I + 1`
done done
fi fi
echo "`date +'%y%m%d %H:%M:%S'` mysqld restarted" | tee -a $err_log echo "`date +'%y%m%d %H:%M:%S'` mysqld restarted" | tee -a $err_log
...@@ -359,3 +349,4 @@ done ...@@ -359,3 +349,4 @@ done
echo "`date +'%y%m%d %H:%M:%S'` mysqld ended" | tee -a $err_log echo "`date +'%y%m%d %H:%M:%S'` mysqld ended" | tee -a $err_log
echo "" | tee -a $err_log echo "" | tee -a $err_log
...@@ -108,7 +108,7 @@ gen_lex_hash.o: gen_lex_hash.cc lex.h ...@@ -108,7 +108,7 @@ gen_lex_hash.o: gen_lex_hash.cc lex.h
sql_yacc.cc: sql_yacc.yy sql_yacc.cc: sql_yacc.yy
sql_yacc.h: sql_yacc.yy sql_yacc.h: sql_yacc.yy
sql_yacc.o: sql_yacc.cc sql_yacc.h sql_yacc.o: sql_yacc.cc sql_yacc.h $(noinst_HEADERS)
@echo "Note: The following compile may take a long time." @echo "Note: The following compile may take a long time."
@echo "If it fails, re-run configure with --with-low-memory" @echo "If it fails, re-run configure with --with-low-memory"
$(CXXCOMPILE) $(LM_CFLAGS) -c $< $(CXXCOMPILE) $(LM_CFLAGS) -c $<
......
...@@ -1221,7 +1221,7 @@ bool MYSQL_LOG::write(Log_event* event_info) ...@@ -1221,7 +1221,7 @@ bool MYSQL_LOG::write(Log_event* event_info)
if (e.write(file)) if (e.write(file))
goto err; goto err;
} }
#if MYSQL_VERSION_ID < 40100 #if MYSQL_VERSION_ID < 40100
if (thd->variables.convert_set) if (thd->variables.convert_set)
{ {
Query_log_event e(thd, "SET CHARACTER SET DEFAULT", 25, 0); Query_log_event e(thd, "SET CHARACTER SET DEFAULT", 25, 0);
...@@ -1682,22 +1682,6 @@ void MYSQL_LOG::set_max_size(ulong max_size_arg) ...@@ -1682,22 +1682,6 @@ void MYSQL_LOG::set_max_size(ulong max_size_arg)
} }
Disable_binlog::Disable_binlog(THD *thd_arg) :
thd(thd_arg),
save_options(thd_arg->options), save_master_access(thd_arg->master_access)
{
thd_arg->options&= ~OPTION_BIN_LOG;
thd_arg->master_access|= SUPER_ACL; // unneeded in 4.1
};
Disable_binlog::~Disable_binlog()
{
thd->options= save_options;
thd->master_access= save_master_access;
}
/* /*
Check if a string is a valid number Check if a string is a valid number
...@@ -1761,15 +1745,21 @@ void print_buffer_to_file(enum loglevel level, const char *buffer) ...@@ -1761,15 +1745,21 @@ void print_buffer_to_file(enum loglevel level, const char *buffer)
skr=time(NULL); skr=time(NULL);
localtime_r(&skr, &tm_tmp); localtime_r(&skr, &tm_tmp);
start=&tm_tmp; start=&tm_tmp;
#if MYSQL_VERSION_ID > 40100
fprintf(stderr, "%02d%02d%02d %2d:%02d:%02d [%s] %s\n", fprintf(stderr, "%02d%02d%02d %2d:%02d:%02d [%s] %s\n",
start->tm_year % 100, #else
start->tm_mon+1, fprintf(stderr, "%02d%02d%02d %2d:%02d:%02d %s\n",
start->tm_mday, #endif
start->tm_hour, start->tm_year % 100,
start->tm_min, start->tm_mon+1,
start->tm_sec, start->tm_mday,
start->tm_hour,
start->tm_min,
start->tm_sec,
#if MYSQL_VERSION_ID > 40100
(level == ERROR_LEVEL ? "ERROR" : level == WARNING_LEVEL ? (level == ERROR_LEVEL ? "ERROR" : level == WARNING_LEVEL ?
"WARNING" : "INFORMATION"), "WARNING" : "INFORMATION"),
#endif
buffer); buffer);
fflush(stderr); fflush(stderr);
......
...@@ -1806,7 +1806,7 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli) ...@@ -1806,7 +1806,7 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli)
{ {
int expected_error, actual_error= 0; int expected_error, actual_error= 0;
init_sql_alloc(&thd->mem_root, thd->variables.query_alloc_block_size,0); init_sql_alloc(&thd->mem_root, thd->variables.query_alloc_block_size,0);
thd->db= (char*) rewrite_db(db); thd->db= (char*) rewrite_db(db); // thd->db_length is set later if needed
/* /*
InnoDB internally stores the master log position it has processed so far; InnoDB internally stores the master log position it has processed so far;
...@@ -1836,6 +1836,11 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli) ...@@ -1836,6 +1836,11 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli)
{ {
thd->set_time((time_t)when); thd->set_time((time_t)when);
thd->current_tablenr = 0; thd->current_tablenr = 0;
/*
We cannot use db_len from event to fill thd->db_length, because
rewrite_db() may have changed db.
*/
thd->db_length= thd->db ? strlen(thd->db) : 0;
thd->query_length= q_len; thd->query_length= q_len;
thd->query= (char *) query; thd->query= (char *) query;
VOID(pthread_mutex_lock(&LOCK_thread_count)); VOID(pthread_mutex_lock(&LOCK_thread_count));
...@@ -1930,7 +1935,7 @@ Default database: '%s'. Query: '%s'", ...@@ -1930,7 +1935,7 @@ Default database: '%s'. Query: '%s'",
VOID(pthread_mutex_lock(&LOCK_thread_count)); VOID(pthread_mutex_lock(&LOCK_thread_count));
thd->db= 0; // prevent db from being freed thd->db= 0; // prevent db from being freed
thd->query= 0; // just to be sure thd->query= 0; // just to be sure
thd->query_length= 0; thd->query_length= thd->db_length =0;
VOID(pthread_mutex_unlock(&LOCK_thread_count)); VOID(pthread_mutex_unlock(&LOCK_thread_count));
close_thread_tables(thd); close_thread_tables(thd);
free_root(&thd->mem_root,MYF(MY_KEEP_PREALLOC)); free_root(&thd->mem_root,MYF(MY_KEEP_PREALLOC));
...@@ -1968,7 +1973,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, ...@@ -1968,7 +1973,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
{ {
char *load_data_query= 0; char *load_data_query= 0;
init_sql_alloc(&thd->mem_root, thd->variables.query_alloc_block_size, 0); init_sql_alloc(&thd->mem_root, thd->variables.query_alloc_block_size, 0);
thd->db= (char*) rewrite_db(db); thd->db= (char*) rewrite_db(db); // thd->db_length is set later if needed
DBUG_ASSERT(thd->query == 0); DBUG_ASSERT(thd->query == 0);
clear_all_errors(thd, rli); clear_all_errors(thd, rli);
...@@ -2001,6 +2006,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, ...@@ -2001,6 +2006,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
{ {
thd->set_time((time_t)when); thd->set_time((time_t)when);
thd->current_tablenr = 0; thd->current_tablenr = 0;
thd->db_length= thd->db ? strlen(thd->db) : 0;
VOID(pthread_mutex_lock(&LOCK_thread_count)); VOID(pthread_mutex_lock(&LOCK_thread_count));
thd->query_id = query_id++; thd->query_id = query_id++;
VOID(pthread_mutex_unlock(&LOCK_thread_count)); VOID(pthread_mutex_unlock(&LOCK_thread_count));
...@@ -2117,7 +2123,7 @@ Slave: load data infile on table '%s' at log position %s in log \ ...@@ -2117,7 +2123,7 @@ Slave: load data infile on table '%s' at log position %s in log \
VOID(pthread_mutex_lock(&LOCK_thread_count)); VOID(pthread_mutex_lock(&LOCK_thread_count));
thd->db= 0; thd->db= 0;
thd->query= 0; thd->query= 0;
thd->query_length= 0; thd->query_length= thd->db_length= 0;
VOID(pthread_mutex_unlock(&LOCK_thread_count)); VOID(pthread_mutex_unlock(&LOCK_thread_count));
close_thread_tables(thd); close_thread_tables(thd);
if (load_data_query) if (load_data_query)
......
...@@ -414,6 +414,7 @@ char mysql_real_data_home[FN_REFLEN], ...@@ -414,6 +414,7 @@ char mysql_real_data_home[FN_REFLEN],
max_sort_char,*mysqld_user,*mysqld_chroot, *opt_init_file; max_sort_char,*mysqld_user,*mysqld_chroot, *opt_init_file;
char *language_ptr= language; char *language_ptr= language;
char mysql_data_home_buff[2], *mysql_data_home=mysql_real_data_home; char mysql_data_home_buff[2], *mysql_data_home=mysql_real_data_home;
struct passwd *user_info;
#ifndef EMBEDDED_LIBRARY #ifndef EMBEDDED_LIBRARY
bool mysql_embedded=0; bool mysql_embedded=0;
#else #else
...@@ -1028,27 +1029,26 @@ static void set_ports() ...@@ -1028,27 +1029,26 @@ static void set_ports()
} }
} }
/* Change to run as another user if started with --user */
static void set_user(const char *user) static struct passwd *check_user(const char *user)
{ {
#if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__) #if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__)
struct passwd *ent; struct passwd *user_info;
uid_t user_id= geteuid(); uid_t user_id= geteuid();
// don't bother if we aren't superuser // Don't bother if we aren't superuser
if (user_id) if (user_id)
{ {
if (user) if (user)
{ {
/* Don't give a warning, if real user is same as given with --user */ // Don't give a warning, if real user is same as given with --user
struct passwd *user_info= getpwnam(user); user_info= getpwnam(user);
if ((!user_info || user_id != user_info->pw_uid) && if ((!user_info || user_id != user_info->pw_uid) &&
global_system_variables.log_warnings) global_system_variables.log_warnings)
fprintf(stderr, fprintf(stderr,
"Warning: One can only use the --user switch if running as root\n"); "Warning: One can only use the --user switch if running as root\n");
} }
return; return NULL;
} }
if (!user) if (!user)
{ {
...@@ -1057,38 +1057,52 @@ static void set_user(const char *user) ...@@ -1057,38 +1057,52 @@ static void set_user(const char *user)
fprintf(stderr,"Fatal error: Please read \"Security\" section of the manual to find out how to run mysqld as root!\n"); fprintf(stderr,"Fatal error: Please read \"Security\" section of the manual to find out how to run mysqld as root!\n");
unireg_abort(1); unireg_abort(1);
} }
return; return NULL;
} }
if (!strcmp(user,"root")) if (!strcmp(user,"root"))
return; // Avoid problem with dynamic libraries return NULL; // Avoid problem with dynamic libraries
if (!(user_info= getpwnam(user)))
uid_t uid;
if (!(ent = getpwnam(user)))
{ {
// allow a numeric uid to be used // Allow a numeric uid to be used
const char *pos; const char *pos;
for (pos=user; isdigit(*pos); pos++) ; for (pos= user; isdigit(*pos); pos++);
if (*pos) // Not numeric id if (*pos) // Not numeric id
{ goto err;
fprintf(stderr,"Fatal error: Can't change to run as user '%s' ; Please check that the user exists!\n",user); if (!(user_info= getpwuid(atoi(user))))
unireg_abort(1); goto err;
} else
uid=atoi(user); // Use numberic uid return user_info;
} }
else else
{ {
return user_info;
}
err:
fprintf(stderr,
"Fatal error: Can't change to run as user '%s'. Please check that the user exists!\n",
user);
unireg_abort(1);
return NULL;
#else
return NULL;
#endif
}
static void set_user(const char *user, struct passwd *user_info)
{
#if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__)
DBUG_ASSERT(user_info);
#ifdef HAVE_INITGROUPS #ifdef HAVE_INITGROUPS
initgroups((char*) user,ent->pw_gid); initgroups((char*) user, user_info->pw_gid);
#endif #endif
if (setgid(ent->pw_gid) == -1) if (setgid(user_info->pw_gid) == -1)
{ {
sql_perror("setgid"); sql_perror("setgid");
unireg_abort(1); unireg_abort(1);
}
uid=ent->pw_uid;
} }
if (setuid(user_info->pw_uid) == -1)
if (setuid(uid) == -1)
{ {
sql_perror("setuid"); sql_perror("setuid");
unireg_abort(1); unireg_abort(1);
...@@ -1096,6 +1110,24 @@ static void set_user(const char *user) ...@@ -1096,6 +1110,24 @@ static void set_user(const char *user)
#endif #endif
} }
static void set_effective_user(struct passwd *user_info)
{
#if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__)
DBUG_ASSERT(user_info);
if (setegid(user_info->pw_gid) == -1)
{
sql_perror("setegid");
unireg_abort(1);
}
if (seteuid(user_info->pw_uid) == -1)
{
sql_perror("seteuid");
unireg_abort(1);
}
#endif
}
/* Change root user if started with --chroot */ /* Change root user if started with --chroot */
static void set_root(const char *path) static void set_root(const char *path)
...@@ -1171,7 +1203,18 @@ static void server_init(void) ...@@ -1171,7 +1203,18 @@ static void server_init(void)
unireg_abort(1); unireg_abort(1);
} }
} }
set_user(mysqld_user); // Works also with mysqld_user==NULL
if ((user_info= check_user(mysqld_user)))
{
#if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT)
if (locked_in_memory && !getuid())
set_effective_user(user_info);
else
set_user(mysqld_user, user_info);
#else
set_user(mysqld_user, user_info);
#endif
}
#ifdef __NT__ #ifdef __NT__
/* create named pipe */ /* create named pipe */
...@@ -2466,8 +2509,13 @@ You should consider changing lower_case_table_names to 1 or 2", ...@@ -2466,8 +2509,13 @@ You should consider changing lower_case_table_names to 1 or 2",
} }
ha_key_cache(); ha_key_cache();
#if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT) #if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT)
if (locked_in_memory && !geteuid()) if (locked_in_memory && !getuid())
{ {
if (seteuid(0) == -1)
{ // this should never happen
sql_perror("seteuid");
unireg_abort(1);
}
if (mlockall(MCL_CURRENT)) if (mlockall(MCL_CURRENT))
{ {
if (global_system_variables.log_warnings) if (global_system_variables.log_warnings)
...@@ -2475,6 +2523,8 @@ You should consider changing lower_case_table_names to 1 or 2", ...@@ -2475,6 +2523,8 @@ You should consider changing lower_case_table_names to 1 or 2",
} }
else else
locked_in_memory=1; locked_in_memory=1;
if (user_info)
set_user(mysqld_user, user_info);
} }
#else #else
locked_in_memory=0; locked_in_memory=0;
......
...@@ -1124,6 +1124,7 @@ slaves can't replicate a 5.0 or newer master."; ...@@ -1124,6 +1124,7 @@ slaves can't replicate a 5.0 or newer master.";
Used by fetch_master_table (used by LOAD TABLE tblname FROM MASTER and LOAD Used by fetch_master_table (used by LOAD TABLE tblname FROM MASTER and LOAD
DATA FROM MASTER). Drops the table (if 'overwrite' is true) and recreates it DATA FROM MASTER). Drops the table (if 'overwrite' is true) and recreates it
from the dump. Honours replication inclusion/exclusion rules. from the dump. Honours replication inclusion/exclusion rules.
db must be non-zero (guarded by assertion).
RETURN VALUES RETURN VALUES
0 success 0 success
...@@ -1134,8 +1135,8 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db, ...@@ -1134,8 +1135,8 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db,
const char* table_name, bool overwrite) const char* table_name, bool overwrite)
{ {
ulong packet_len = my_net_read(net); // read create table statement ulong packet_len = my_net_read(net); // read create table statement
char *query; char *query, *save_db;
char* save_db; uint32 save_db_length;
Vio* save_vio; Vio* save_vio;
HA_CHECK_OPT check_opt; HA_CHECK_OPT check_opt;
TABLE_LIST tables; TABLE_LIST tables;
...@@ -1193,9 +1194,13 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db, ...@@ -1193,9 +1194,13 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db,
thd->proc_info = "Creating table from master dump"; thd->proc_info = "Creating table from master dump";
// save old db in case we are creating in a different database // save old db in case we are creating in a different database
save_db = thd->db; save_db = thd->db;
save_db_length= thd->db_length;
thd->db = (char*)db; thd->db = (char*)db;
DBUG_ASSERT(thd->db);
thd->db_length= strlen(thd->db);
mysql_parse(thd, thd->query, packet_len); // run create table mysql_parse(thd, thd->query, packet_len); // run create table
thd->db = save_db; // leave things the way the were before thd->db = save_db; // leave things the way the were before
thd->db_length= save_db_length;
thd->options = save_options; thd->options = save_options;
if (thd->query_error) if (thd->query_error)
...@@ -2689,7 +2694,7 @@ log space"); ...@@ -2689,7 +2694,7 @@ log space");
IO_RPL_LOG_NAME, llstr(mi->master_log_pos,llbuff)); IO_RPL_LOG_NAME, llstr(mi->master_log_pos,llbuff));
VOID(pthread_mutex_lock(&LOCK_thread_count)); VOID(pthread_mutex_lock(&LOCK_thread_count));
thd->query = thd->db = 0; // extra safety thd->query = thd->db = 0; // extra safety
thd->query_length = 0; thd->query_length= thd->db_length= 0;
VOID(pthread_mutex_unlock(&LOCK_thread_count)); VOID(pthread_mutex_unlock(&LOCK_thread_count));
if (mysql) if (mysql)
{ {
...@@ -2838,7 +2843,7 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \ ...@@ -2838,7 +2843,7 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \
err: err:
VOID(pthread_mutex_lock(&LOCK_thread_count)); VOID(pthread_mutex_lock(&LOCK_thread_count));
thd->query = thd->db = 0; // extra safety thd->query = thd->db = 0; // extra safety
thd->query_length = 0; thd->query_length= thd->db_length= 0;
VOID(pthread_mutex_unlock(&LOCK_thread_count)); VOID(pthread_mutex_unlock(&LOCK_thread_count));
thd->proc_info = "Waiting for slave mutex on exit"; thd->proc_info = "Waiting for slave mutex on exit";
pthread_mutex_lock(&rli->run_lock); pthread_mutex_lock(&rli->run_lock);
......
...@@ -810,6 +810,13 @@ void field_real::get_opt_type(String *answer, ...@@ -810,6 +810,13 @@ void field_real::get_opt_type(String *answer,
if (min_arg >= 0) if (min_arg >= 0)
answer->append(" UNSIGNED"); answer->append(" UNSIGNED");
} }
else if (item->decimals == NOT_FIXED_DEC)
{
if (min_arg >= -FLT_MAX && max_arg <= FLT_MAX)
answer->append("FLOAT", 5);
else
answer->append("DOUBLE", 6);
}
else else
{ {
if (min_arg >= -FLT_MAX && max_arg <= FLT_MAX) if (min_arg >= -FLT_MAX && max_arg <= FLT_MAX)
......
...@@ -638,27 +638,6 @@ class THD :public ilink ...@@ -638,27 +638,6 @@ class THD :public ilink
#define SYSTEM_THREAD_SLAVE_IO 2 #define SYSTEM_THREAD_SLAVE_IO 2
#define SYSTEM_THREAD_SLAVE_SQL 4 #define SYSTEM_THREAD_SLAVE_SQL 4
/*
Disables binary logging for one thread, and resets it back to what it was
before being disabled.
Some functions (like the internal mysql_create_table() when it's called by
mysql_alter_table()) must NOT write to the binlog (binlogging is done at the
at a later stage of the command already, and must be, for locking reasons);
so we internally disable it temporarily by creating the Disable_binlog
object and reset the state by destroying the object (don't forget that! or
write code so that the object gets automatically destroyed when leaving a
block, see example in sql_table.cc).
*/
class Disable_binlog {
private:
THD *thd;
ulong save_options;
ulong save_master_access;
public:
Disable_binlog(THD *thd_arg);
~Disable_binlog();
};
/* /*
Used to hold information about file and file structure in exchainge Used to hold information about file and file structure in exchainge
via non-DB file (...INTO OUTFILE..., ...LOAD DATA...) via non-DB file (...INTO OUTFILE..., ...LOAD DATA...)
......
...@@ -385,6 +385,15 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, ...@@ -385,6 +385,15 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db,
} }
/*
Changes the current database.
NOTES
Do as little as possible in this function, as it is not called for the
replication slave SQL thread (for that thread, setting of thd->db is done
in ::exec_event() methods of log_event.cc).
*/
bool mysql_change_db(THD *thd,const char *name) bool mysql_change_db(THD *thd,const char *name)
{ {
int length, db_length; int length, db_length;
......
...@@ -30,6 +30,16 @@ ...@@ -30,6 +30,16 @@
#include <io.h> #include <io.h>
#endif #endif
#include "sql_acl.h" // for SUPER_ACL
# define tmp_disable_binlog(A) \
ulong save_options= (A)->options, save_master_access= (A)->master_access; \
(A)->options&= ~OPTION_BIN_LOG; \
(A)->master_access|= SUPER_ACL; /* unneeded in 4.1 */
#define reenable_binlog(A) \
(A)->options= save_options; \
(A)->master_access= save_master_access;
extern HASH open_cache; extern HASH open_cache;
static const char *primary_key_name="PRIMARY"; static const char *primary_key_name="PRIMARY";
...@@ -840,9 +850,8 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, ...@@ -840,9 +850,8 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
MYSQL_LOCK **lock) MYSQL_LOCK **lock)
{ {
TABLE tmp_table; // Used during 'create_field()' TABLE tmp_table; // Used during 'create_field()'
TABLE *table; TABLE *table= 0;
tmp_table.table_name=0; tmp_table.table_name=0;
Disable_binlog disable_binlog(thd);
DBUG_ENTER("create_table_from_items"); DBUG_ENTER("create_table_from_items");
/* Add selected items to field list */ /* Add selected items to field list */
...@@ -872,23 +881,25 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, ...@@ -872,23 +881,25 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
extra_fields->push_back(cr_field); extra_fields->push_back(cr_field);
} }
/* create and lock table */ /* create and lock table */
/* QQ: This should be done atomic ! */ /* QQ: create and open should be done atomic ! */
/* We don't log the statement, it will be logged later */
if (mysql_create_table(thd,db,name,create_info,*extra_fields,
*keys,0))
DBUG_RETURN(0);
/* /*
We don't log the statement, it will be logged later.
If this is a HEAP table, the automatic DELETE FROM which is written to the If this is a HEAP table, the automatic DELETE FROM which is written to the
binlog when a HEAP table is opened for the first time since startup, must binlog when a HEAP table is opened for the first time since startup, must
not be written: 1) it would be wrong (imagine we're in CREATE SELECT: we not be written: 1) it would be wrong (imagine we're in CREATE SELECT: we
don't want to delete from it) 2) it would be written before the CREATE don't want to delete from it) 2) it would be written before the CREATE
TABLE, which is a wrong order. So we keep binary logging disabled. TABLE, which is a wrong order. So we keep binary logging disabled when we
open_table().
*/ */
if (!(table=open_table(thd,db,name,name,(bool*) 0))) tmp_disable_binlog(thd);
if (!mysql_create_table(thd,db,name,create_info,*extra_fields,*keys,0))
{ {
quick_rm_table(create_info->db_type,db,table_case_name(create_info,name)); if (!(table=open_table(thd,db,name,name,(bool*) 0)))
DBUG_RETURN(0); quick_rm_table(create_info->db_type,db,table_case_name(create_info,name));
} }
reenable_binlog(thd);
if (!table)
DBUG_RETURN(0);
table->reginfo.lock_type=TL_WRITE; table->reginfo.lock_type=TL_WRITE;
if (!((*lock)=mysql_lock_tables(thd,&table,1))) if (!((*lock)=mysql_lock_tables(thd,&table,1)))
{ {
...@@ -1925,14 +1936,12 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -1925,14 +1936,12 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
else else
create_info->data_file_name=create_info->index_file_name=0; create_info->data_file_name=create_info->index_file_name=0;
{ {
/* /* We don't log the statement, it will be logged later. */
We don't log the statement, it will be logged later. Using a block so tmp_disable_binlog(thd);
that disable_binlog is deleted when we leave it in either way. error= mysql_create_table(thd, new_db, tmp_name,
*/ create_info,create_list,key_list,1);
Disable_binlog disable_binlog(thd); reenable_binlog(thd);
if ((error=mysql_create_table(thd, new_db, tmp_name, if (error)
create_info,
create_list,key_list,1)))
DBUG_RETURN(error); DBUG_RETURN(error);
} }
if (table->tmp_table) if (table->tmp_table)
......
...@@ -148,6 +148,10 @@ int mysql_union(THD *thd, LEX *lex,select_result *result) ...@@ -148,6 +148,10 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
{ {
ha_rows records_at_start; ha_rows records_at_start;
lex->select=sl; lex->select=sl;
#if MYSQL_VERSION_ID < 40100
if (describe && sl->linkage == NOT_A_SELECT)
break; // Skip extra item in case of 'explain'
#endif
/* Don't use offset for the last union if there is no braces */ /* Don't use offset for the last union if there is no braces */
if (sl != lex_sl) if (sl != lex_sl)
{ {
......
...@@ -2917,7 +2917,7 @@ show_param: ...@@ -2917,7 +2917,7 @@ show_param:
lex->select->select_limit= lex->thd->variables.select_limit; lex->select->select_limit= lex->thd->variables.select_limit;
lex->select->offset_limit= 0L; lex->select->offset_limit= 0L;
} limit_clause } limit_clause
| keys_or_index FROM table_ident opt_db | keys_or_index from_or_in table_ident opt_db
{ {
Lex->sql_command= SQLCOM_SHOW_KEYS; Lex->sql_command= SQLCOM_SHOW_KEYS;
if ($4) if ($4)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment