diff options
author | monty@tik.mysql.fi <> | 2002-02-13 22:37:19 +0200 |
---|---|---|
committer | monty@tik.mysql.fi <> | 2002-02-13 22:37:19 +0200 |
commit | 2f3cfff0a2b4ed75ff3086440ba5a7bd6f4f75cb (patch) | |
tree | f93a6d7f74bfe9a525304996a4bd5c965e755e8c | |
parent | 4abd402b87def3f292f77b4091493675d9a37589 (diff) | |
download | mariadb-git-2f3cfff0a2b4ed75ff3086440ba5a7bd6f4f75cb.tar.gz |
Added --user=userid to mysqld
Fix for ctypes on windows
Cleanup max_queries_per_hour
-rw-r--r-- | Docs/manual.texi | 8 | ||||
-rw-r--r-- | include/m_ctype.h | 26 | ||||
-rw-r--r-- | mysql-test/r/dirty_close.result (renamed from mysql-test/r/dirty-close.result) | 0 | ||||
-rw-r--r-- | mysql-test/r/join.result | 22 | ||||
-rw-r--r-- | mysql-test/t/dirty_close.test (renamed from mysql-test/t/dirty-close.test) | 0 | ||||
-rw-r--r-- | sql/mysqld.cc | 29 | ||||
-rw-r--r-- | sql/sql_parse.cc | 111 |
7 files changed, 116 insertions, 80 deletions
diff --git a/Docs/manual.texi b/Docs/manual.texi index d075e17ee56..3b8c8da822c 100644 --- a/Docs/manual.texi +++ b/Docs/manual.texi @@ -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} directory resides on a partition too small to hold temporary tables. -@item -u, --user=user_name -Run @code{mysqld} daemon as user @code{user_name}. This option is -@emph{mandatory} when starting @code{mysqld} as root. +@item -u, --user= [user_name | userid] +Run @code{mysqld} daemon as user @code{user_name} or @code{userid} (numeric). +This option is @emph{mandatory} when starting @code{mysqld} as root. @item -V, --version 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 @item +Allow numeric user id to @code{mysqld --user=#}. +@item 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. @item diff --git a/include/m_ctype.h b/include/m_ctype.h index 05f49784802..61afcb7245e 100644 --- a/include/m_ctype.h +++ b/include/m_ctype.h @@ -62,9 +62,6 @@ extern const char *compiled_charset_name(uint charset_number); #define MY_CHARSET_UNDEFINED 0 #define MY_CHARSET_CURRENT (default_charset_info->number) -#ifdef __WIN__ -#include <ctype.h> -#endif /* Don't include std ctype.h when this is included */ #define _CTYPE_H #define _CTYPE_H_ @@ -72,6 +69,26 @@ extern const char *compiled_charset_name(uint charset_number); #define __CTYPE_INCLUDED #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 _L 02 /* Lower case */ #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_sort_order (default_charset_info->sort_order) -#ifndef __WIN__ #define _toupper(c) (char) my_to_upper[(uchar) (c)] #define _tolower(c) (char) my_to_lower[(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 #endif /* ctype */ -#endif /* __WIN__ */ - #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_islower(s, c) (((s)->ctype+1)[(uchar) (c)] & _L) diff --git a/mysql-test/r/dirty-close.result b/mysql-test/r/dirty_close.result index c4fc19a35f8..c4fc19a35f8 100644 --- a/mysql-test/r/dirty-close.result +++ b/mysql-test/r/dirty_close.result diff --git a/mysql-test/r/join.result b/mysql-test/r/join.result index 5069fbaf527..b8ec13e9f50 100644 --- a/mysql-test/r/join.result +++ b/mysql-test/r/join.result @@ -186,3 +186,25 @@ t3.CanRead='1' AND t3.Active='1'; COUNT(t1.Title) 1 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; diff --git a/mysql-test/t/dirty-close.test b/mysql-test/t/dirty_close.test index 3ed22f26d5b..3ed22f26d5b 100644 --- a/mysql-test/t/dirty-close.test +++ b/mysql-test/t/dirty_close.test diff --git a/sql/mysqld.cc b/sql/mysqld.cc index d1d3d6072d6..b5789dd0ff8 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -856,20 +856,33 @@ static void set_user(const char *user) if (!strcmp(user,"root")) return; // Avoid problem with dynamic libraries + uid_t uid; if (!(ent = getpwnam(user))) { - fprintf(stderr,"Fatal error: Can't change to run as user '%s' ; Please check that the user exists!\n",user); - unireg_abort(1); + // allow a numeric uid to be used + 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 } + else + { #ifdef HAVE_INITGROUPS - initgroups((char*) user,ent->pw_gid); + initgroups((char*) user,ent->pw_gid); #endif - if (setgid(ent->pw_gid) == -1) - { - sql_perror("setgid"); - unireg_abort(1); + 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"); unireg_abort(1); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index d1f9c2bafdc..01327363c59 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -120,8 +120,9 @@ inline bool end_active_trans(THD *thd) static HASH hash_user_connections; extern pthread_mutex_t LOCK_user_conn; -static int get_or_create_user_conn(THD *thd, const char *user, const char *host, - uint max_questions) +static int get_or_create_user_conn(THD *thd, const char *user, + const char *host, + uint max_questions) { int return_val=0; 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, NullS) - temp_user); (void) pthread_mutex_lock(&LOCK_user_conn); - uc = (struct user_conn *) hash_search(&hash_user_connections, - (byte*) temp_user, temp_len); - if (!uc) + if (!(uc = (struct user_conn *) hash_search(&hash_user_connections, + (byte*) temp_user, temp_len))) { - uc= ((struct user_conn*) - my_malloc(sizeof(struct user_conn) + temp_len+1, - MYF(MY_WME))); - if (!uc) - { + /* First connection for user; Create a user connection object */ + if (!(uc= ((struct user_conn*) + my_malloc(sizeof(struct user_conn) + temp_len+1, + MYF(MY_WME))) + { send_error(¤t_thd->net, 0, NullS); // Out of memory return_val=1; goto end; - } + } uc->user=(char*) (uc+1); memcpy(uc->user,temp_user,temp_len+1); uc->len = temp_len; @@ -280,9 +280,6 @@ static int check_for_max_user_connections(UC *uc) { int error=0; 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) { @@ -303,8 +300,6 @@ static void decrease_user_connections(UC *uc) return; DBUG_ENTER("decrease_user_connections"); - DBUG_ASSERT(uc != 0); -// DBUG_PRINT("enter",("user: '%s' host: '%s'", user, host)); 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 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) @@ -335,15 +334,14 @@ static bool check_mqh(THD *thd) UC *uc=thd->user_connect; DBUG_ASSERT(uc != 0); - /* TODO: Add username + host to THD for faster execution */ bool my_start = thd->start_time != 0; time_t check_time = (my_start) ? thd->start_time : time(NULL); if (check_time - uc->intime >= 3600) { -// (void) pthread_mutex_lock(&LOCK_user_conn); - uc->questions=(uint) my_start; + (void) pthread_mutex_lock(&LOCK_user_conn); + uc->questions=1; 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) { @@ -357,27 +355,22 @@ end: DBUG_RETURN(error); } -static void reset_mqh(THD *thd,LEX_USER *lu, uint mq) + +static void reset_mqh(THD *thd, LEX_USER *lu, uint mq) { - char user[USERNAME_LENGTH+1]; - char host[USERNAME_LENGTH+1]; - char *where; + (void) pthread_mutex_lock(&LOCK_user_conn); if (lu) // for GRANT { UC *uc; - uint temp_len; + uint temp_len=lu->user.length+lu->host.length+2; char temp_user[USERNAME_LENGTH+HOSTNAME_LENGTH+2]; - memcpy(user,lu->user.str,lu->user.length); - user[lu->user.length]='\0'; - memcpy(host,lu->host.str,lu->host.length); - host[lu->host.length]='\0'; - temp_len= (uint) (strxnmov(temp_user, sizeof(temp_user)-1, user, "@", host, - NullS) - temp_user); - uc = (struct user_conn *) hash_search(&hash_user_connections, - (byte*) temp_user, temp_len); - if (uc) + memcpy(temp_user,lu->user.str,lu->user.length); + memcpy(temp_user+lu->user.length+1,lu->host.str,lu->host.length); + temp_user[lu->user.length]=temp_user[temp_len-1]=0; + if ((uc = (struct user_conn *) hash_search(&hash_user_connections, + (byte*) temp_user, temp_len))) { uc->questions=0; uc->max_questions=mq; @@ -385,21 +378,20 @@ static void reset_mqh(THD *thd,LEX_USER *lu, uint mq) } 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*); - UC *uc=(struct user_conn *)data->data; + char user[USERNAME_LENGTH+1]; + char *where; + UC *uc=(struct user_conn *) hash_element(&hash_element, idx); where=strchr(uc->user,'@'); - memcpy(user,uc->user,where - uc->user); - user[where-uc->user]='\0'; where++; - strcpy(host,where); - uc->max_questions=get_mqh(user,host); + strmake(user,uc->user,where - uc->user); + uc->max_questions=get_mqh(user,where+1); } - (void) pthread_mutex_unlock(&LOCK_user_conn); } + (void) pthread_mutex_unlock(&LOCK_user_conn); } + /* Check connnetion and get priviliges 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; 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; DBUG_ENTER("dispatch_command"); @@ -913,7 +907,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, break; } if (max_connections && save_uc) - decrease_user_connections (save_uc); + decrease_user_connections(save_uc); x_free((gptr) save_db); x_free((gptr) save_user); 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)); if (thd->user_connect && check_mqh(thd)) { - error = TRUE; - net->error = 0; + error = TRUE; // Abort client + net->error = 0; // Don't give abort message break; } /* thd->query_length is set by mysql_parse() */ @@ -1072,11 +1066,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, else send_eof(net); if (mqh_used) - { - if (hash_user_connections.array.buffer == 0) - init_max_user_conn(); - reset_mqh(thd,(LEX_USER *)NULL,0); - } + reset_mqh(thd,(LEX_USER *) NULL, 0); break; } case COM_SHUTDOWN: @@ -2306,17 +2296,12 @@ mysql_execute_command(void) Query_log_event qinfo(thd, thd->query); mysql_bin_log.write(&qinfo); } - if (mqh_used) + if (mqh_used && lex->mqh) { - if (hash_user_connections.array.buffer == 0) - init_max_user_conn(); - if (lex->mqh) - { - List_iterator <LEX_USER> str_list (lex->users_list); - LEX_USER *Str; - str_list.rewind(); - reset_mqh(thd,str_list++,lex->mqh); - } + List_iterator <LEX_USER> str_list(lex->users_list); + LEX_USER *user; + while ((user=str_list++)) + reset_mqh(thd,user,lex->mqh); } } } |