summaryrefslogtreecommitdiff
path: root/sql/sql_parse.cc
diff options
context:
space:
mode:
authorunknown <Sinisa@sinisa.nasamreza.org>2002-05-15 13:50:38 +0300
committerunknown <Sinisa@sinisa.nasamreza.org>2002-05-15 13:50:38 +0300
commitc5bfcc9d7f3c77def9a8df65da11a6b55c2edea5 (patch)
treea860fbee06b7b609760f7c02085992e96887e9ce /sql/sql_parse.cc
parent2b0dd9c9666314f57f5f3aae6af7087b02d0b316 (diff)
downloadmariadb-git-c5bfcc9d7f3c77def9a8df65da11a6b55c2edea5.tar.gz
Features made for Schlund plus several bug fixes.
Read a manual for more detail
Diffstat (limited to 'sql/sql_parse.cc')
-rw-r--r--sql/sql_parse.cc175
1 files changed, 111 insertions, 64 deletions
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index dc89888a1a5..af68c1bb9f3 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -59,9 +59,9 @@ extern "C" pthread_mutex_t THR_LOCK_keycache;
extern "C" int gethostname(char *name, int namelen);
#endif
-static int check_for_max_user_connections(UC *uc);
+static int check_for_max_user_connections(USER_CONN *uc);
static bool check_mqh(THD *thd);
-static void decrease_user_connections(UC *uc);
+static void decrease_user_connections(USER_CONN *uc);
static bool check_db_used(THD *thd,TABLE_LIST *tables);
static bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *tables);
static bool check_dup(const char *db, const char *name, TABLE_LIST *tables);
@@ -126,18 +126,19 @@ 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)
+ USER_RESOURCES *mqh)
{
int return_val=0;
- uint temp_len;
+ uint temp_len, user_len, host_len;
char temp_user[USERNAME_LENGTH+HOSTNAME_LENGTH+2];
struct user_conn *uc;
DBUG_ASSERT(user != 0);
DBUG_ASSERT(host != 0);
- temp_len= (uint) (strxnmov(temp_user, sizeof(temp_user)-1, user, "@", host,
- NullS) - temp_user);
+ user_len=strlen(user);
+ host_len=strlen(host);
+ temp_len= (strmov(strmov(temp_user, user)+1, host) - temp_user)+1;
(void) pthread_mutex_lock(&LOCK_user_conn);
if (!(uc = (struct user_conn *) hash_search(&hash_user_connections,
(byte*) temp_user, temp_len)))
@@ -153,10 +154,14 @@ static int get_or_create_user_conn(THD *thd, const char *user,
}
uc->user=(char*) (uc+1);
memcpy(uc->user,temp_user,temp_len+1);
+ uc->user_len= user_len;
+ uc->host=uc->user + uc->user_len + 1;
uc->len = temp_len;
- uc->connections = 1;
- uc->questions=0;
- uc->max_questions=max_questions;
+ uc->connections = 1;
+ uc->questions=uc->updates=uc->conn_per_hour=0;
+ uc->user_resources=*mqh;
+ if (mqh->connections > max_user_connections)
+ uc->user_resources.connections = max_user_connections;
uc->intime=thd->thr_create_time;
if (hash_insert(&hash_user_connections, (byte*) uc))
{
@@ -184,9 +189,9 @@ static bool check_user(THD *thd,enum_server_command command, const char *user,
const char *passwd, const char *db, bool check_count)
{
NET *net= &thd->net;
- uint max_questions=0;
thd->db=0;
thd->db_length=0;
+ USER_RESOURCES ur;
if (!(thd->user = my_strdup(user, MYF(0))))
{
@@ -197,7 +202,7 @@ static bool check_user(THD *thd,enum_server_command command, const char *user,
passwd, thd->scramble, &thd->priv_user,
protocol_version == 9 ||
!(thd->client_capabilities &
- CLIENT_LONG_PASSWORD),&max_questions);
+ CLIENT_LONG_PASSWORD),&ur);
DBUG_PRINT("info",
("Capabilities: %d packet_length: %d Host: '%s' User: '%s' Using password: %s Access: %u db: '%s'",
thd->client_capabilities, thd->max_packet_length,
@@ -237,9 +242,9 @@ static bool check_user(THD *thd,enum_server_command command, const char *user,
db ? db : (char*) "");
thd->db_access=0;
/* Don't allow user to connect if he has done too many queries */
- if ((max_questions || max_user_connections) && get_or_create_user_conn(thd,user,thd->host_or_ip,max_questions))
+ if ((ur.questions || ur.updates || ur.connections) && get_or_create_user_conn(thd,user,thd->host_or_ip,&ur))
return -1;
- if (max_user_connections && thd->user_connect &&
+ if (thd->user_connect && thd->user_connect->user_resources.connections &&
check_for_max_user_connections(thd->user_connect))
return -1;
if (db && db[0])
@@ -279,32 +284,43 @@ void init_max_user_conn(void)
}
-static int check_for_max_user_connections(UC *uc)
+static int check_for_max_user_connections(USER_CONN *uc)
{
int error=0;
DBUG_ENTER("check_for_max_user_connections");
- if (max_user_connections <= (uint) uc->connections)
+ if (max_user_connections && ( max_user_connections <= (uint) uc->connections))
{
net_printf(&(current_thd->net),ER_TOO_MANY_USER_CONNECTIONS, uc->user);
error=1;
goto end;
}
uc->connections++;
-
+if (uc->user_resources.connections && uc->conn_per_hour++ >= uc->user_resources.connections)
+ {
+ net_printf(&current_thd->net, ER_USER_LIMIT_REACHED, uc->user, "max_connections",
+ (long) uc->user_resources.connections);
+ error=1;
+ goto end;
+ }
end:
DBUG_RETURN(error);
}
-static void decrease_user_connections(UC *uc)
+static void decrease_user_connections(USER_CONN *uc)
{
- if (!max_user_connections)
+/* if (!max_user_connections)
return;
+*/
DBUG_ENTER("decrease_user_connections");
-
- if (!--uc->connections && !mqh_used)
+ if (mqh_used)
+ {
+ if (uc->conn_per_hour)
+ uc->conn_per_hour--;
+ }
+ else if (!--uc->connections)
{
/* Last connection for user; Delete it */
(void) pthread_mutex_lock(&LOCK_user_conn);
@@ -325,70 +341,92 @@ 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 %
+ In theory we would need a mutex in the USER_CONN 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.
*/
+char uc_update_queries[SQLCOM_END];
+
static bool check_mqh(THD *thd)
{
bool error=0;
DBUG_ENTER("check_mqh");
- UC *uc=thd->user_connect;
+ USER_CONN *uc=thd->user_connect;
DBUG_ASSERT(uc != 0);
+ uint check_command = thd->lex.sql_command;
+
- bool my_start = thd->start_time != 0;
- time_t check_time = (my_start) ? thd->start_time : time(NULL);
- if (check_time - uc->intime >= 3600)
+ if (check_command < (uint) SQLCOM_END)
{
- (void) pthread_mutex_lock(&LOCK_user_conn);
- uc->questions=1;
- uc->intime=check_time;
- (void) pthread_mutex_unlock(&LOCK_user_conn);
+ if (uc->user_resources.updates && uc_update_queries[check_command] &&
+ ++(uc->updates) > uc->user_resources.updates)
+ {
+ net_printf(&thd->net, ER_USER_LIMIT_REACHED, uc->user, "max_updates",
+ (long) uc->user_resources.updates);
+ error=1;
+ goto end;
+ }
}
- else if (uc->max_questions && ++(uc->questions) > uc->max_questions)
+ else
{
- net_printf(&thd->net, ER_USER_LIMIT_REACHED, uc->user, "max_questions",
- (long) uc->max_questions);
- error=1;
- goto end;
+ 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=1;
+ uc->updates=0;
+ uc->conn_per_hour=0;
+ uc->intime=check_time;
+ (void) pthread_mutex_unlock(&LOCK_user_conn);
+ }
+ else if (uc->user_resources.questions && ++(uc->questions) > uc->user_resources.questions)
+ {
+ net_printf(&thd->net, ER_USER_LIMIT_REACHED, uc->user, "max_questions",
+ (long) uc->user_resources.questions);
+ error=1;
+ goto end;
+ }
}
-
end:
DBUG_RETURN(error);
}
-static void reset_mqh(THD *thd, LEX_USER *lu, uint mq)
+static void reset_mqh(THD *thd, LEX_USER *lu, USER_RESOURCES *mqh, bool get_them=false)
{
(void) pthread_mutex_lock(&LOCK_user_conn);
if (lu) // for GRANT
{
- UC *uc;
+ USER_CONN *uc;
uint temp_len=lu->user.length+lu->host.length+2;
char temp_user[USERNAME_LENGTH+HOSTNAME_LENGTH+2];
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;
+ temp_user[lu->user.length]='\0'; temp_user[temp_len-1]=0;
if ((uc = (struct user_conn *) hash_search(&hash_user_connections,
- (byte*) temp_user, temp_len)))
+ (byte*) temp_user, temp_len-1)))
{
uc->questions=0;
- uc->max_questions=mq;
+ uc->user_resources=*mqh;
+ uc->updates=0;
+ uc->conn_per_hour=0;
}
}
- else // for FLUSH PRIVILEGES
+ else // for FLUSH PRIVILEGES and FLUSH USER_RESOURCES
{
for (uint idx=0;idx < hash_user_connections.records; idx++)
{
- char user[USERNAME_LENGTH+1];
- char *where;
- UC *uc=(struct user_conn *) hash_element(&hash_user_connections, idx);
- where=strchr(uc->user,'@');
- strmake(user,uc->user,where - uc->user);
- uc->max_questions=get_mqh(user,where+1);
+ USER_CONN *uc=(struct user_conn *) hash_element(&hash_user_connections, idx);
+ if (get_them)
+ get_mqh(uc->user,uc->host,uc);
+ uc->questions=0;
+ uc->updates=0;
+ uc->conn_per_hour=0;
}
}
(void) pthread_mutex_unlock(&LOCK_user_conn);
@@ -708,7 +746,7 @@ pthread_handler_decl(handle_bootstrap,arg)
thd->query= thd->memdup_w_gap(buff, length+1, thd->db_length+1);
thd->query[length] = '\0';
thd->query_id=query_id++;
- if (thd->user_connect && check_mqh(thd))
+ if (mqh_used && thd->user_connect && check_mqh(thd))
{
thd->net.error = 0;
close_thread_tables(thd); // Free tables
@@ -895,7 +933,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
char *save_user= thd->user;
char *save_priv_user= thd->priv_user;
char *save_db= thd->db;
- UC *save_uc= thd->user_connect;
+ USER_CONN *save_uc= thd->user_connect;
if ((uint) ((uchar*) db - net->read_pos) > packet_length)
{ // Check if protocol is ok
@@ -948,7 +986,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
my_pthread_setprio(pthread_self(),QUERY_PRIOR);
mysql_log.write(thd,command,"%s",thd->query);
DBUG_PRINT("query",("%s",thd->query));
- if (thd->user_connect && check_mqh(thd))
+ if (mqh_used && thd->user_connect && check_mqh(thd))
{
error = TRUE; // Abort client
net->error = 0; // Don't give abort message
@@ -1073,8 +1111,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
send_error(net,0);
else
send_eof(net);
- if (mqh_used)
- reset_mqh(thd,(LEX_USER *) NULL, 0);
break;
}
case COM_SHUTDOWN:
@@ -2316,12 +2352,12 @@ mysql_execute_command(void)
Query_log_event qinfo(thd, thd->query);
mysql_bin_log.write(&qinfo);
}
- if (mqh_used && lex->mqh)
+ if (mqh_used && (lex->mqh.questions || lex->mqh.updates || lex->mqh.connections) && lex->sql_command == SQLCOM_GRANT)
{
List_iterator <LEX_USER> str_list(lex->users_list);
LEX_USER *user;
while ((user=str_list++))
- reset_mqh(thd,user,lex->mqh);
+ reset_mqh(thd,user,&(lex->mqh));
}
}
}
@@ -2727,8 +2763,15 @@ mysql_parse(THD *thd,char *inBuf,uint length)
LEX *lex=lex_start(thd, (uchar*) inBuf, length);
if (!yyparse() && ! thd->fatal_error)
{
- mysql_execute_command();
- query_cache_end_of_result(&thd->net);
+ if (mqh_used && thd->user_connect && check_mqh(thd))
+ {
+ thd->net.error = 0;
+ }
+ else
+ {
+ mysql_execute_command();
+ query_cache_end_of_result(&thd->net);
+ }
}
else
query_cache_abort(&thd->net);
@@ -3272,6 +3315,8 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables)
{
acl_reload();
grant_reload();
+ if (mqh_used)
+ reset_mqh(thd,(LEX_USER *) NULL, 0, true);
}
if (options & REFRESH_LOG)
{
@@ -3318,14 +3363,16 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables)
result=load_des_key_file(des_key_file);
}
#endif
- if (options & REFRESH_SLAVE)
- {
- LOCK_ACTIVE_MI;
- if (reset_slave(active_mi))
- result=1;
- UNLOCK_ACTIVE_MI;
- }
- return result;
+ if (options & REFRESH_SLAVE)
+ {
+ LOCK_ACTIVE_MI;
+ if (reset_slave(active_mi))
+ result=1;
+ UNLOCK_ACTIVE_MI;
+ }
+ if (options & REFRESH_USER_RESOURCES)
+ reset_mqh(thd,(LEX_USER *) NULL, 0);
+ return result;
}