1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00

merge with 4.0

BitKeeper/etc/ignore:
  auto-union
BitKeeper/etc/logging_ok:
  auto-union
BUILD/SETUP.sh:
  Auto merged
BUILD/compile-pentium-debug:
  Auto merged
BitKeeper/triggers/post-commit:
  Auto merged
configure.in:
  Auto merged
Docs/manual.texi:
  Auto merged
client/mysql.cc:
  Auto merged
client/mysqldump.c:
  Auto merged
client/mysqltest.c:
  Auto merged
extra/mysql_install.c:
  Auto merged
extra/resolve_stack_dump.c:
  Auto merged
extra/resolveip.c:
  Auto merged
include/my_sys.h:
  Auto merged
include/mysqld_error.h:
  Auto merged
isam/pack_isam.c:
  Auto merged
libmysql/Makefile.shared:
  Auto merged
libmysql/libmysql.c:
  Auto merged
myisam/ft_dump.c:
  Auto merged
myisam/ft_test1.c:
  Auto merged
myisam/ftdefs.h:
  Auto merged
myisam/mi_check.c:
  Auto merged
myisam/mi_test1.c:
  Auto merged
myisam/mi_write.c:
  Auto merged
myisam/myisamchk.c:
  Auto merged
myisam/myisampack.c:
  Auto merged
mysql-test/mysql-test-run.sh:
  Auto merged
mysql-test/r/select_found.result:
  Auto merged
mysql-test/t/select_found.test:
  Auto merged
mysys/charset.c:
  Auto merged
mysys/default.c:
  Auto merged
mysys/hash.c:
  Auto merged
sql/field.cc:
  Auto merged
sql/gen_lex_hash.cc:
  Auto merged
sql/ha_innodb.cc:
  Auto merged
sql/hostname.cc:
  Auto merged
sql/item_cmpfunc.h:
  Auto merged
sql/item_strfunc.cc:
  Auto merged
sql/item_timefunc.h:
  Auto merged
sql/lex.h:
  Auto merged
sql/log.cc:
  Auto merged
sql/mysql_priv.h:
  Auto merged
sql/repl_failsafe.cc:
  Auto merged
sql/slave.cc:
  Auto merged
sql/sql_acl.cc:
  Auto merged
sql/sql_base.cc:
  Auto merged
sql/sql_cache.cc:
  Auto merged
sql/sql_class.cc:
  Auto merged
sql/sql_class.h:
  Auto merged
sql/sql_db.cc:
  Auto merged
sql/sql_parse.cc:
  Auto merged
sql/sql_select.cc:
  Auto merged
sql/sql_string.cc:
  Auto merged
sql/sql_table.cc:
  Auto merged
sql/sql_union.cc:
  Auto merged
sql/share/czech/errmsg.txt:
  Auto merged
sql/share/danish/errmsg.txt:
  Auto merged
sql/share/dutch/errmsg.txt:
  Auto merged
sql/share/english/errmsg.txt:
  Auto merged
sql/share/estonian/errmsg.txt:
  Auto merged
sql/share/german/errmsg.txt:
  Auto merged
sql/share/greek/errmsg.txt:
  Auto merged
sql/share/hungarian/errmsg.txt:
  Auto merged
sql/share/italian/errmsg.txt:
  Auto merged
sql/share/japanese/errmsg.txt:
  Auto merged
sql/share/korean/errmsg.txt:
  Auto merged
sql/share/norwegian-ny/errmsg.txt:
  Auto merged
sql/share/norwegian/errmsg.txt:
  Auto merged
sql/sql_update.cc:
  Auto merged
sql/structs.h:
  Auto merged
sql/share/polish/errmsg.txt:
  Auto merged
sql/share/portuguese/errmsg.txt:
  Auto merged
sql/share/romanian/errmsg.txt:
  Auto merged
sql/share/russian/errmsg.txt:
  Auto merged
sql/share/slovak/errmsg.txt:
  Auto merged
sql/share/spanish/errmsg.txt:
  Auto merged
sql/share/swedish/errmsg.txt:
  Auto merged
sql/share/ukrainian/errmsg.txt:
  Auto merged
strings/Makefile.am:
  Auto merged
strings/ctype-ujis.c:
  Auto merged
tools/mysqlmanager.c:
  Auto merged
This commit is contained in:
unknown
2002-06-03 12:59:31 +03:00
1035 changed files with 12202 additions and 98503 deletions

View File

@ -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 (max_user_connections && 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,10 @@ 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])
@ -254,6 +260,7 @@ static bool check_user(THD *thd,enum_server_command command, const char *user,
return 0; // ok
}
/*
Check for maximum allowable user connections, if the mysqld server is
started with corresponding variable that is greater then 0.
@ -280,32 +287,38 @@ 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 && uc->connections && !--uc->connections)
{
/* Last connection for user; Delete it */
(void) pthread_mutex_lock(&LOCK_user_conn);
@ -326,70 +339,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);
@ -710,7 +745,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
@ -897,7 +932,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
@ -951,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
@ -1010,7 +1045,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
thread_safe_increment(com_stat[SQLCOM_CREATE_DB],&LOCK_thread_count);
char *db=thd->strdup(packet);
// null test to handle EOM
if (!db || !stripp_sp(db) || check_db_name(db))
if (!db || !strip_sp(db) || check_db_name(db))
{
net_printf(&thd->net,ER_WRONG_DB_NAME, db ? db : "NULL");
break;
@ -1026,7 +1061,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
thread_safe_increment(com_stat[SQLCOM_DROP_DB],&LOCK_thread_count);
char *db=thd->strdup(packet);
// null test to handle EOM
if (!db || !stripp_sp(db) || check_db_name(db))
if (!db || !strip_sp(db) || check_db_name(db))
{
net_printf(&thd->net,ER_WRONG_DB_NAME, db ? db : "NULL");
break;
@ -1076,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:
@ -1680,7 +1713,6 @@ mysql_execute_command(void)
check_table_access(thd,SELECT_ACL | INSERT_ACL, tables))
goto error; /* purecov: inspected */
res = mysql_repair_table(thd, tables, &lex->check_opt);
query_cache_invalidate3(thd, tables, 0);
break;
}
case SQLCOM_CHECK:
@ -1689,7 +1721,6 @@ mysql_execute_command(void)
check_table_access(thd, SELECT_ACL | EXTRA_ACL , tables))
goto error; /* purecov: inspected */
res = mysql_check_table(thd, tables, &lex->check_opt);
query_cache_invalidate3(thd, tables, 0);
break;
}
case SQLCOM_ANALYZE:
@ -1772,6 +1803,7 @@ mysql_execute_command(void)
tables->grant.want_privilege=(SELECT_ACL & ~tables->grant.privilege);
if ((res=open_and_lock_tables(thd,tables)))
break;
thd->select_limit=HA_POS_ERROR;
if (!setup_fields(thd,tables,select_lex->item_list,1,0,0) &&
!setup_fields(thd,tables,lex->value_list,0,0,0) && ! thd->fatal_error &&
(result=new multi_update(thd,tables,select_lex->item_list,lex->duplicates,
@ -1952,8 +1984,9 @@ mysql_execute_command(void)
/* Fix tables-to-be-deleted-from list to point at opened tables */
for (auxi=(TABLE_LIST*) aux_tables ; auxi ; auxi=auxi->next)
auxi->table= ((TABLE_LIST*) auxi->table)->table;
if (!thd->fatal_error && (result=new multi_delete(thd,aux_tables,
lex->lock_option,table_count)))
if (!thd->fatal_error && (result= new multi_delete(thd,aux_tables,
lex->lock_option,
table_count)))
{
res=mysql_select(thd,tables,select_lex->item_list,
select_lex->where,
@ -2198,7 +2231,8 @@ mysql_execute_command(void)
}
if (check_db_used(thd,tables) || end_active_trans(thd))
goto error;
if (grant_option && check_grant(thd,SELECT_ACL | INSERT_ACL | UPDATE_ACL | DELETE_ACL,tables))
if (check_table_access(thd, SELECT_ACL | INSERT_ACL | UPDATE_ACL | DELETE_ACL , tables)
|| (grant_option && check_grant(thd,SELECT_ACL | INSERT_ACL | UPDATE_ACL | DELETE_ACL,tables)))
goto error;
thd->in_lock_tables=1;
thd->options|= OPTION_TABLE_LOCK;
@ -2214,7 +2248,7 @@ mysql_execute_command(void)
break;
case SQLCOM_CREATE_DB:
{
if (!stripp_sp(lex->name) || check_db_name(lex->name))
if (!strip_sp(lex->name) || check_db_name(lex->name))
{
net_printf(&thd->net,ER_WRONG_DB_NAME, lex->name);
break;
@ -2226,7 +2260,7 @@ mysql_execute_command(void)
}
case SQLCOM_DROP_DB:
{
if (!stripp_sp(lex->name) || check_db_name(lex->name))
if (!strip_sp(lex->name) || check_db_name(lex->name))
{
net_printf(&thd->net,ER_WRONG_DB_NAME, lex->name);
break;
@ -2328,12 +2362,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));
}
}
}
@ -2721,7 +2755,7 @@ void mysql_init_multi_delete(LEX *lex)
{
lex->sql_command = SQLCOM_DELETE_MULTI;
mysql_init_select(lex);
lex->select->select_limit=HA_POS_ERROR;
lex->select->select_limit=lex->thd->select_limit=HA_POS_ERROR;
lex->auxilliary_table_list=lex->select_lex.table_list;
lex->select->table_list.elements=0;
lex->select->table_list.first=0;
@ -2740,8 +2774,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);
@ -2842,9 +2883,9 @@ bool add_field_to_list(char *field_name, enum_field_types type,
uint sign_len=type_modifier & UNSIGNED_FLAG ? 0 : 1;
if (new_field->length && new_field->decimals &&
new_field->length < new_field->decimals+2 &&
new_field->length < new_field->decimals+1 &&
new_field->decimals != NOT_FIXED_DEC)
new_field->length=new_field->decimals+2; /* purecov: inspected */
new_field->length=new_field->decimals+1; /* purecov: inspected */
switch (type) {
case FIELD_TYPE_TINY:
@ -2972,7 +3013,9 @@ bool add_field_to_list(char *field_name, enum_field_types type,
new_field->interval=interval;
new_field->length=0;
for (const char **pos=interval->type_names; *pos ; pos++)
new_field->length+=(uint) strlen(*pos)+1;
{
new_field->length+=(uint) strip_sp((char*) *pos)+1;
}
new_field->length--;
set_if_smaller(new_field->length,MAX_FIELD_WIDTH-1);
if (default_value)
@ -2993,10 +3036,10 @@ bool add_field_to_list(char *field_name, enum_field_types type,
{
new_field->interval=interval;
new_field->pack_length=interval->count < 256 ? 1 : 2; // Should be safe
new_field->length=(uint) strlen(interval->type_names[0]);
new_field->length=(uint) strip_sp((char*) interval->type_names[0]);
for (const char **pos=interval->type_names+1; *pos ; pos++)
{
uint length=(uint) strlen(*pos);
uint length=(uint) strip_sp((char*) *pos);
set_if_bigger(new_field->length,length);
}
set_if_smaller(new_field->length,MAX_FIELD_WIDTH-1);
@ -3299,6 +3342,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)
{
@ -3345,14 +3390,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;
}