Added --user=userid to mysqld
Fix for ctypes on windows Cleanup max_queries_per_hour mysql-test/t/dirty_close.test: Rename: mysql-test/t/dirty-close.test -> mysql-test/t/dirty_close.test mysql-test/r/dirty_close.result: Rename: mysql-test/r/dirty-close.result -> mysql-test/r/dirty_close.result Docs/manual.texi: Added --user=userid include/m_ctype.h: Fix for ctypes on windows mysql-test/r/join.result: Update join results sql/mysqld.cc: Added --user=userid sql/sql_parse.cc: Cleanup max_queries_per_hour
This commit is contained in:
parent
e0ccdc17a2
commit
429abf3560
@ -14207,9 +14207,9 @@ Sets the default transaction isolation level. @xref{SET TRANSACTION}.
|
|||||||
Path for temporary files. It may be useful if your default @code{/tmp}
|
Path for temporary files. It may be useful if your default @code{/tmp}
|
||||||
directory resides on a partition too small to hold temporary tables.
|
directory resides on a partition too small to hold temporary tables.
|
||||||
|
|
||||||
@item -u, --user=user_name
|
@item -u, --user= [user_name | userid]
|
||||||
Run @code{mysqld} daemon as user @code{user_name}. This option is
|
Run @code{mysqld} daemon as user @code{user_name} or @code{userid} (numeric).
|
||||||
@emph{mandatory} when starting @code{mysqld} as root.
|
This option is @emph{mandatory} when starting @code{mysqld} as root.
|
||||||
|
|
||||||
@item -V, --version
|
@item -V, --version
|
||||||
Output version information and exit.
|
Output version information and exit.
|
||||||
@ -48411,6 +48411,8 @@ Our TODO section contains what we plan to have in 4.0. @xref{TODO MySQL 4.0}.
|
|||||||
|
|
||||||
@itemize @bullet
|
@itemize @bullet
|
||||||
@item
|
@item
|
||||||
|
Allow numeric user id to @code{mysqld --user=#}.
|
||||||
|
@item
|
||||||
Fixed a bug where @code{SQL_CALC_ROWS} returned a wrong value when used
|
Fixed a bug where @code{SQL_CALC_ROWS} returned a wrong value when used
|
||||||
with one table and @code{ORDER BY} and with InnoDB tables.
|
with one table and @code{ORDER BY} and with InnoDB tables.
|
||||||
@item
|
@item
|
||||||
|
@ -62,9 +62,6 @@ extern const char *compiled_charset_name(uint charset_number);
|
|||||||
#define MY_CHARSET_UNDEFINED 0
|
#define MY_CHARSET_UNDEFINED 0
|
||||||
#define MY_CHARSET_CURRENT (default_charset_info->number)
|
#define MY_CHARSET_CURRENT (default_charset_info->number)
|
||||||
|
|
||||||
#ifdef __WIN__
|
|
||||||
#include <ctype.h>
|
|
||||||
#endif
|
|
||||||
/* Don't include std ctype.h when this is included */
|
/* Don't include std ctype.h when this is included */
|
||||||
#define _CTYPE_H
|
#define _CTYPE_H
|
||||||
#define _CTYPE_H_
|
#define _CTYPE_H_
|
||||||
@ -72,6 +69,26 @@ extern const char *compiled_charset_name(uint charset_number);
|
|||||||
#define __CTYPE_INCLUDED
|
#define __CTYPE_INCLUDED
|
||||||
#define _CTYPE_USING /* Don't put names in global namespace. */
|
#define _CTYPE_USING /* Don't put names in global namespace. */
|
||||||
|
|
||||||
|
/* Fix things, if ctype.h would have been included before */
|
||||||
|
#undef toupper
|
||||||
|
#undef _toupper
|
||||||
|
#undef _tolower
|
||||||
|
#undef toupper
|
||||||
|
#undef tolower
|
||||||
|
#undef isalpha
|
||||||
|
#undef isupper
|
||||||
|
#undef islower
|
||||||
|
#undef isdigit
|
||||||
|
#undef isxdigit
|
||||||
|
#undef isalnum
|
||||||
|
#undef isspace
|
||||||
|
#undef ispunct
|
||||||
|
#undef isprint
|
||||||
|
#undef isgraph
|
||||||
|
#undef iscntrl
|
||||||
|
#undef isascii
|
||||||
|
#undef toascii
|
||||||
|
|
||||||
#define _U 01 /* Upper case */
|
#define _U 01 /* Upper case */
|
||||||
#define _L 02 /* Lower case */
|
#define _L 02 /* Lower case */
|
||||||
#define _N 04 /* Numeral (digit) */
|
#define _N 04 /* Numeral (digit) */
|
||||||
@ -86,7 +103,6 @@ extern const char *compiled_charset_name(uint charset_number);
|
|||||||
#define my_to_lower (default_charset_info->to_lower)
|
#define my_to_lower (default_charset_info->to_lower)
|
||||||
#define my_sort_order (default_charset_info->sort_order)
|
#define my_sort_order (default_charset_info->sort_order)
|
||||||
|
|
||||||
#ifndef __WIN__
|
|
||||||
#define _toupper(c) (char) my_to_upper[(uchar) (c)]
|
#define _toupper(c) (char) my_to_upper[(uchar) (c)]
|
||||||
#define _tolower(c) (char) my_to_lower[(uchar) (c)]
|
#define _tolower(c) (char) my_to_lower[(uchar) (c)]
|
||||||
#define toupper(c) (char) my_to_upper[(uchar) (c)]
|
#define toupper(c) (char) my_to_upper[(uchar) (c)]
|
||||||
@ -110,8 +126,6 @@ extern const char *compiled_charset_name(uint charset_number);
|
|||||||
#undef ctype
|
#undef ctype
|
||||||
#endif /* ctype */
|
#endif /* ctype */
|
||||||
|
|
||||||
#endif /* __WIN__ */
|
|
||||||
|
|
||||||
#define my_isalpha(s, c) (((s)->ctype+1)[(uchar) (c)] & (_U | _L))
|
#define my_isalpha(s, c) (((s)->ctype+1)[(uchar) (c)] & (_U | _L))
|
||||||
#define my_isupper(s, c) (((s)->ctype+1)[(uchar) (c)] & _U)
|
#define my_isupper(s, c) (((s)->ctype+1)[(uchar) (c)] & _U)
|
||||||
#define my_islower(s, c) (((s)->ctype+1)[(uchar) (c)] & _L)
|
#define my_islower(s, c) (((s)->ctype+1)[(uchar) (c)] & _L)
|
||||||
|
@ -186,3 +186,25 @@ t3.CanRead='1' AND t3.Active='1';
|
|||||||
COUNT(t1.Title)
|
COUNT(t1.Title)
|
||||||
1
|
1
|
||||||
drop table t1,t2,t3;
|
drop table t1,t2,t3;
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
t1_id int(11) default NULL,
|
||||||
|
t2_id int(11) default NULL,
|
||||||
|
type enum('Cost','Percent') default NULL,
|
||||||
|
cost_unit enum('Cost','Unit') default NULL,
|
||||||
|
min_value double default NULL,
|
||||||
|
max_value double default NULL,
|
||||||
|
t3_id int(11) default NULL,
|
||||||
|
item_id int(11) default NULL
|
||||||
|
) TYPE=MyISAM;
|
||||||
|
INSERT INTO t1 VALUES (12,5,'Percent','Cost',-1,0,-1,-1),(14,4,'Percent','Cost',-1,0,-1,-1),(18,5,'Percent','Cost',-1,0,-1,-1),(19,4,'Percent','Cost',-1,0,-1,-1),(20,5,'Percent','Cost',100,-1,22,291),(21,5,'Percent','Cost',100,-1,18,291),(22,1,'Percent','Cost',100,-1,6,291),(23,1,'Percent','Cost',100,-1,21,291),(24,1,'Percent','Cost',100,-1,9,291),(25,1,'Percent','Cost',100,-1,4,291),(26,1,'Percent','Cost',100,-1,20,291),(27,4,'Percent','Cost',100,-1,7,202),(28,1,'Percent','Cost',50,-1,-1,137),(29,2,'Percent','Cost',100,-1,4,354),(30,2,'Percent','Cost',100,-1,9,137),(93,2,'Cost','Cost',-1,10000000,-1,-1);
|
||||||
|
CREATE TABLE t2 (
|
||||||
|
id int(10) unsigned NOT NULL auto_increment,
|
||||||
|
name varchar(255) default NULL,
|
||||||
|
PRIMARY KEY (id)
|
||||||
|
) TYPE=MyISAM;
|
||||||
|
INSERT INTO t2 VALUES (1,'s1'),(2,'s2'),(3,'s3'),(4,'s4'),(5,'s5');
|
||||||
|
select t1.*, t2.* from t1, t2 where t2.id=t1.t2_id limit 2;
|
||||||
|
t1_id t2_id type cost_unit min_value max_value t3_id item_id id name
|
||||||
|
22 1 Percent Cost 100 -1 6 291 1 s1
|
||||||
|
23 1 Percent Cost 100 -1 21 291 1 s1
|
||||||
|
drop table t1,t2;
|
||||||
|
@ -856,20 +856,33 @@ static void set_user(const char *user)
|
|||||||
if (!strcmp(user,"root"))
|
if (!strcmp(user,"root"))
|
||||||
return; // Avoid problem with dynamic libraries
|
return; // Avoid problem with dynamic libraries
|
||||||
|
|
||||||
|
uid_t uid;
|
||||||
if (!(ent = getpwnam(user)))
|
if (!(ent = getpwnam(user)))
|
||||||
{
|
{
|
||||||
fprintf(stderr,"Fatal error: Can't change to run as user '%s' ; Please check that the user exists!\n",user);
|
// allow a numeric uid to be used
|
||||||
unireg_abort(1);
|
const char *pos;
|
||||||
|
for (pos=user; isdigit(*pos); pos++) ;
|
||||||
|
if (*pos) // Not numeric id
|
||||||
|
{
|
||||||
|
fprintf(stderr,"Fatal error: Can't change to run as user '%s' ; Please check that the user exists!\n",user);
|
||||||
|
unireg_abort(1);
|
||||||
|
}
|
||||||
|
uid=atoi(user); // Use numberic uid
|
||||||
}
|
}
|
||||||
#ifdef HAVE_INITGROUPS
|
else
|
||||||
initgroups((char*) user,ent->pw_gid);
|
|
||||||
#endif
|
|
||||||
if (setgid(ent->pw_gid) == -1)
|
|
||||||
{
|
{
|
||||||
sql_perror("setgid");
|
#ifdef HAVE_INITGROUPS
|
||||||
unireg_abort(1);
|
initgroups((char*) user,ent->pw_gid);
|
||||||
|
#endif
|
||||||
|
if (setgid(ent->pw_gid) == -1)
|
||||||
|
{
|
||||||
|
sql_perror("setgid");
|
||||||
|
unireg_abort(1);
|
||||||
|
}
|
||||||
|
uid=ent->pw_uid;
|
||||||
}
|
}
|
||||||
if (setuid(ent->pw_uid) == -1)
|
|
||||||
|
if (setuid(uid) == -1)
|
||||||
{
|
{
|
||||||
sql_perror("setuid");
|
sql_perror("setuid");
|
||||||
unireg_abort(1);
|
unireg_abort(1);
|
||||||
|
113
sql/sql_parse.cc
113
sql/sql_parse.cc
@ -120,8 +120,9 @@ inline bool end_active_trans(THD *thd)
|
|||||||
static HASH hash_user_connections;
|
static HASH hash_user_connections;
|
||||||
extern pthread_mutex_t LOCK_user_conn;
|
extern pthread_mutex_t LOCK_user_conn;
|
||||||
|
|
||||||
static int get_or_create_user_conn(THD *thd, const char *user, const char *host,
|
static int get_or_create_user_conn(THD *thd, const char *user,
|
||||||
uint max_questions)
|
const char *host,
|
||||||
|
uint max_questions)
|
||||||
{
|
{
|
||||||
int return_val=0;
|
int return_val=0;
|
||||||
uint temp_len;
|
uint temp_len;
|
||||||
@ -134,19 +135,18 @@ static int get_or_create_user_conn(THD *thd, const char *user, const char *host,
|
|||||||
temp_len= (uint) (strxnmov(temp_user, sizeof(temp_user)-1, user, "@", host,
|
temp_len= (uint) (strxnmov(temp_user, sizeof(temp_user)-1, user, "@", host,
|
||||||
NullS) - temp_user);
|
NullS) - temp_user);
|
||||||
(void) pthread_mutex_lock(&LOCK_user_conn);
|
(void) pthread_mutex_lock(&LOCK_user_conn);
|
||||||
uc = (struct user_conn *) hash_search(&hash_user_connections,
|
if (!(uc = (struct user_conn *) hash_search(&hash_user_connections,
|
||||||
(byte*) temp_user, temp_len);
|
(byte*) temp_user, temp_len)))
|
||||||
if (!uc)
|
|
||||||
{
|
{
|
||||||
uc= ((struct user_conn*)
|
/* First connection for user; Create a user connection object */
|
||||||
my_malloc(sizeof(struct user_conn) + temp_len+1,
|
if (!(uc= ((struct user_conn*)
|
||||||
MYF(MY_WME)));
|
my_malloc(sizeof(struct user_conn) + temp_len+1,
|
||||||
if (!uc)
|
MYF(MY_WME)))
|
||||||
{
|
{
|
||||||
send_error(¤t_thd->net, 0, NullS); // Out of memory
|
send_error(¤t_thd->net, 0, NullS); // Out of memory
|
||||||
return_val=1;
|
return_val=1;
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
uc->user=(char*) (uc+1);
|
uc->user=(char*) (uc+1);
|
||||||
memcpy(uc->user,temp_user,temp_len+1);
|
memcpy(uc->user,temp_user,temp_len+1);
|
||||||
uc->len = temp_len;
|
uc->len = temp_len;
|
||||||
@ -280,9 +280,6 @@ static int check_for_max_user_connections(UC *uc)
|
|||||||
{
|
{
|
||||||
int error=0;
|
int error=0;
|
||||||
DBUG_ENTER("check_for_max_user_connections");
|
DBUG_ENTER("check_for_max_user_connections");
|
||||||
// DBUG_PRINT("enter",("user: '%s' host: '%s'", user, host));
|
|
||||||
|
|
||||||
DBUG_ASSERT(uc != 0);
|
|
||||||
|
|
||||||
if (max_user_connections <= (uint) uc->connections)
|
if (max_user_connections <= (uint) uc->connections)
|
||||||
{
|
{
|
||||||
@ -303,8 +300,6 @@ static void decrease_user_connections(UC *uc)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
DBUG_ENTER("decrease_user_connections");
|
DBUG_ENTER("decrease_user_connections");
|
||||||
DBUG_ASSERT(uc != 0);
|
|
||||||
// DBUG_PRINT("enter",("user: '%s' host: '%s'", user, host));
|
|
||||||
|
|
||||||
if (!--uc->connections && !mqh_used)
|
if (!--uc->connections && !mqh_used)
|
||||||
{
|
{
|
||||||
@ -326,6 +321,10 @@ void free_max_user_conn(void)
|
|||||||
/*
|
/*
|
||||||
Check if maximum queries per hour limit has been reached
|
Check if maximum queries per hour limit has been reached
|
||||||
returns 0 if OK.
|
returns 0 if OK.
|
||||||
|
|
||||||
|
In theory we would need a mutex in the UC structure for this to be 100 %
|
||||||
|
safe, but as the worst scenario is that we would miss counting a couple of
|
||||||
|
queries, this isn't critical.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static bool check_mqh(THD *thd)
|
static bool check_mqh(THD *thd)
|
||||||
@ -335,15 +334,14 @@ static bool check_mqh(THD *thd)
|
|||||||
UC *uc=thd->user_connect;
|
UC *uc=thd->user_connect;
|
||||||
DBUG_ASSERT(uc != 0);
|
DBUG_ASSERT(uc != 0);
|
||||||
|
|
||||||
/* TODO: Add username + host to THD for faster execution */
|
|
||||||
bool my_start = thd->start_time != 0;
|
bool my_start = thd->start_time != 0;
|
||||||
time_t check_time = (my_start) ? thd->start_time : time(NULL);
|
time_t check_time = (my_start) ? thd->start_time : time(NULL);
|
||||||
if (check_time - uc->intime >= 3600)
|
if (check_time - uc->intime >= 3600)
|
||||||
{
|
{
|
||||||
// (void) pthread_mutex_lock(&LOCK_user_conn);
|
(void) pthread_mutex_lock(&LOCK_user_conn);
|
||||||
uc->questions=(uint) my_start;
|
uc->questions=1;
|
||||||
uc->intime=check_time;
|
uc->intime=check_time;
|
||||||
// (void) pthread_mutex_unlock(&LOCK_user_conn);
|
(void) pthread_mutex_unlock(&LOCK_user_conn);
|
||||||
}
|
}
|
||||||
else if (uc->max_questions && ++(uc->questions) > uc->max_questions)
|
else if (uc->max_questions && ++(uc->questions) > uc->max_questions)
|
||||||
{
|
{
|
||||||
@ -357,27 +355,22 @@ end:
|
|||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void reset_mqh(THD *thd,LEX_USER *lu, uint mq)
|
|
||||||
{
|
|
||||||
char user[USERNAME_LENGTH+1];
|
|
||||||
char host[USERNAME_LENGTH+1];
|
|
||||||
char *where;
|
|
||||||
|
|
||||||
|
static void reset_mqh(THD *thd, LEX_USER *lu, uint mq)
|
||||||
|
{
|
||||||
|
|
||||||
|
(void) pthread_mutex_lock(&LOCK_user_conn);
|
||||||
if (lu) // for GRANT
|
if (lu) // for GRANT
|
||||||
{
|
{
|
||||||
UC *uc;
|
UC *uc;
|
||||||
uint temp_len;
|
uint temp_len=lu->user.length+lu->host.length+2;
|
||||||
char temp_user[USERNAME_LENGTH+HOSTNAME_LENGTH+2];
|
char temp_user[USERNAME_LENGTH+HOSTNAME_LENGTH+2];
|
||||||
|
|
||||||
memcpy(user,lu->user.str,lu->user.length);
|
memcpy(temp_user,lu->user.str,lu->user.length);
|
||||||
user[lu->user.length]='\0';
|
memcpy(temp_user+lu->user.length+1,lu->host.str,lu->host.length);
|
||||||
memcpy(host,lu->host.str,lu->host.length);
|
temp_user[lu->user.length]=temp_user[temp_len-1]=0;
|
||||||
host[lu->host.length]='\0';
|
if ((uc = (struct user_conn *) hash_search(&hash_user_connections,
|
||||||
temp_len= (uint) (strxnmov(temp_user, sizeof(temp_user)-1, user, "@", host,
|
(byte*) temp_user, temp_len)))
|
||||||
NullS) - temp_user);
|
|
||||||
uc = (struct user_conn *) hash_search(&hash_user_connections,
|
|
||||||
(byte*) temp_user, temp_len);
|
|
||||||
if (uc)
|
|
||||||
{
|
{
|
||||||
uc->questions=0;
|
uc->questions=0;
|
||||||
uc->max_questions=mq;
|
uc->max_questions=mq;
|
||||||
@ -385,21 +378,20 @@ static void reset_mqh(THD *thd,LEX_USER *lu, uint mq)
|
|||||||
}
|
}
|
||||||
else // for FLUSH PRIVILEGES
|
else // for FLUSH PRIVILEGES
|
||||||
{
|
{
|
||||||
(void) pthread_mutex_lock(&LOCK_user_conn);
|
for (uint idx=0;idx < hash_user_connections.records; idx++)
|
||||||
for (uint idx=0;idx<hash_user_connections.records;idx++)
|
|
||||||
{
|
{
|
||||||
HASH_LINK *data=dynamic_element(&hash_user_connections.array,idx,HASH_LINK*);
|
char user[USERNAME_LENGTH+1];
|
||||||
UC *uc=(struct user_conn *)data->data;
|
char *where;
|
||||||
|
UC *uc=(struct user_conn *) hash_element(&hash_element, idx);
|
||||||
where=strchr(uc->user,'@');
|
where=strchr(uc->user,'@');
|
||||||
memcpy(user,uc->user,where - uc->user);
|
strmake(user,uc->user,where - uc->user);
|
||||||
user[where-uc->user]='\0'; where++;
|
uc->max_questions=get_mqh(user,where+1);
|
||||||
strcpy(host,where);
|
|
||||||
uc->max_questions=get_mqh(user,host);
|
|
||||||
}
|
}
|
||||||
(void) pthread_mutex_unlock(&LOCK_user_conn);
|
|
||||||
}
|
}
|
||||||
|
(void) pthread_mutex_unlock(&LOCK_user_conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Check connnetion and get priviliges
|
Check connnetion and get priviliges
|
||||||
Returns 0 on ok, -1 < if error is given > 0 on error.
|
Returns 0 on ok, -1 < if error is given > 0 on error.
|
||||||
@ -834,8 +826,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
|||||||
{
|
{
|
||||||
NET *net= &thd->net;
|
NET *net= &thd->net;
|
||||||
bool error=0;
|
bool error=0;
|
||||||
// commands which will always take a long time should be marked with
|
/*
|
||||||
// this so that they will not get logged to the slow query log
|
Commands which will always take a long time should be marked with
|
||||||
|
this so that they will not get logged to the slow query log
|
||||||
|
*/
|
||||||
bool slow_command=FALSE;
|
bool slow_command=FALSE;
|
||||||
DBUG_ENTER("dispatch_command");
|
DBUG_ENTER("dispatch_command");
|
||||||
|
|
||||||
@ -913,7 +907,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (max_connections && save_uc)
|
if (max_connections && save_uc)
|
||||||
decrease_user_connections (save_uc);
|
decrease_user_connections(save_uc);
|
||||||
x_free((gptr) save_db);
|
x_free((gptr) save_db);
|
||||||
x_free((gptr) save_user);
|
x_free((gptr) save_user);
|
||||||
thd->password=test(passwd[0]);
|
thd->password=test(passwd[0]);
|
||||||
@ -948,8 +942,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
|||||||
DBUG_PRINT("query",("%s",thd->query));
|
DBUG_PRINT("query",("%s",thd->query));
|
||||||
if (thd->user_connect && check_mqh(thd))
|
if (thd->user_connect && check_mqh(thd))
|
||||||
{
|
{
|
||||||
error = TRUE;
|
error = TRUE; // Abort client
|
||||||
net->error = 0;
|
net->error = 0; // Don't give abort message
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* thd->query_length is set by mysql_parse() */
|
/* thd->query_length is set by mysql_parse() */
|
||||||
@ -1072,11 +1066,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
|||||||
else
|
else
|
||||||
send_eof(net);
|
send_eof(net);
|
||||||
if (mqh_used)
|
if (mqh_used)
|
||||||
{
|
reset_mqh(thd,(LEX_USER *) NULL, 0);
|
||||||
if (hash_user_connections.array.buffer == 0)
|
|
||||||
init_max_user_conn();
|
|
||||||
reset_mqh(thd,(LEX_USER *)NULL,0);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case COM_SHUTDOWN:
|
case COM_SHUTDOWN:
|
||||||
@ -2306,17 +2296,12 @@ mysql_execute_command(void)
|
|||||||
Query_log_event qinfo(thd, thd->query);
|
Query_log_event qinfo(thd, thd->query);
|
||||||
mysql_bin_log.write(&qinfo);
|
mysql_bin_log.write(&qinfo);
|
||||||
}
|
}
|
||||||
if (mqh_used)
|
if (mqh_used && lex->mqh)
|
||||||
{
|
{
|
||||||
if (hash_user_connections.array.buffer == 0)
|
List_iterator <LEX_USER> str_list(lex->users_list);
|
||||||
init_max_user_conn();
|
LEX_USER *user;
|
||||||
if (lex->mqh)
|
while ((user=str_list++))
|
||||||
{
|
reset_mqh(thd,user,lex->mqh);
|
||||||
List_iterator <LEX_USER> str_list (lex->users_list);
|
|
||||||
LEX_USER *Str;
|
|
||||||
str_list.rewind();
|
|
||||||
reset_mqh(thd,str_list++,lex->mqh);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user