summaryrefslogtreecommitdiff
path: root/sql/sql_base.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_base.cc')
-rw-r--r--sql/sql_base.cc226
1 files changed, 149 insertions, 77 deletions
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 6185b031c2e..a8115c15412 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -19,7 +19,6 @@
#include "mysql_priv.h"
#include "sql_acl.h"
-#include <thr_alarm.h>
#include <m_ctype.h>
#include <my_dir.h>
#include <hash.h>
@@ -33,7 +32,7 @@ TABLE *unused_tables; /* Used by mysql_test */
HASH open_cache; /* Used by mysql_test */
static int open_unireg_entry(THD *thd,TABLE *entry,const char *db,
- const char *name, const char *alias, bool locked);
+ const char *name, const char *alias);
static void free_cache_entry(TABLE *entry);
static void mysql_rm_tmp_tables(void);
static key_map get_key_map_from_key_list(TABLE *table,
@@ -110,10 +109,27 @@ static void check_unused(void)
#define check_unused()
#endif
+/*
+ Create a list for all open tables matching SQL expression
+
+ SYNOPSIS
+ list_open_tables()
+ thd Thread THD
+ wild SQL like expression
+
+ NOTES
+ One gets only a list of tables for which one has any kind of privilege.
+ db and table names are allocated in result struct, so one doesn't need
+ a lock on LOCK_open when traversing the return list.
+
+ RETURN VALUES
+ NULL Error (Probably OOM)
+ # Pointer to list of names of open tables.
+*/
+
OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *wild)
{
int result = 0;
- uint col_access=thd->col_access;
OPEN_TABLE_LIST **start_list, *open_list;
TABLE_LIST table_list;
char name[NAME_LEN*2];
@@ -179,13 +195,25 @@ OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *wild)
DBUG_RETURN(open_list);
}
+
/*
- Send name and type of result to client.
- Sum fields has table name empty and field_name.
- flag is a bit mask with the following functions:
- 1 send number of rows
- 2 send default values
- 4 Don't convert field names
+ Send name and type of result to client converted to a given char set
+
+ SYNOPSIS
+ send_convert_fields()
+ THD Thread data object
+ list List of items to send to client
+ convert object used to convertation to another character set
+ flag Bit mask with the following functions:
+ 2 send default values
+ 4 Don't convert field names
+
+ DESCRIPTION
+ Sum fields has table name empty and field_name.
+
+ RETURN VALUES
+ 0 ok
+ 1 Error (Note that in this case the error is not sent to the client)
*/
bool
@@ -194,16 +222,15 @@ send_convert_fields(THD *thd,List<Item> &list,CONVERT *convert,uint flag)
List_iterator_fast<Item> it(list);
Item *item;
char buff[80];
-
String tmp((char*) buff,sizeof(buff),default_charset_info);
String *res,*packet= &thd->packet;
-
+ DBUG_ENTER("send_fields");
+
while ((item=it++))
{
char *pos;
Send_field field;
item->make_field(&field);
-
packet->length(0);
if (thd->client_capabilities & CLIENT_PROTOCOL_41)
@@ -219,7 +246,7 @@ send_convert_fields(THD *thd,List<Item> &list,CONVERT *convert,uint flag)
convert->store(packet,field.org_col_name,
(uint) strlen(field.org_col_name)) ||
packet->realloc(packet->length()+10))
- return 1;
+ goto err;
}
else
{
@@ -228,9 +255,8 @@ send_convert_fields(THD *thd,List<Item> &list,CONVERT *convert,uint flag)
convert->store(packet,field.col_name,
(uint) strlen(field.col_name)) ||
packet->realloc(packet->length()+10))
- return 1;
+ goto err;
}
-
pos= (char*) packet->ptr()+packet->length();
if (!(thd->client_capabilities & CLIENT_LONG_FLAG))
@@ -252,24 +278,38 @@ send_convert_fields(THD *thd,List<Item> &list,CONVERT *convert,uint flag)
if (!(res=item->val_str(&tmp)))
{
if (net_store_null(packet))
- return 1;
+ goto err;
}
- else if (net_store_data(packet,res->ptr(),res->length()))
- return 1;
+ else if (convert->store(packet,res->ptr(),res->length()))
+ goto err;
}
if (my_net_write(&thd->net, (char*) packet->ptr(),packet->length()))
break; /* purecov: inspected */
}
return 0;
+
+err:
+ return 1;
}
+
/*
- Send name and type of result to client.
- Sum fields has table name empty and field_name
- flag is a bit mask with the following functios:
- 1 send number of rows
- 2 send default values
- 4 Don't convert field names
+ Send name and type of result to client.
+
+ SYNOPSIS
+ send_non_convert_fields()
+ THD Thread data object
+ list List of items to send to client
+ flag Bit mask with the following functions:
+ 2 send default values
+ 4 Don't convert field names
+
+ DESCRIPTION
+ Sum fields has table name empty and field_name.
+
+ RETURN VALUES
+ 0 ok
+ 1 Error
*/
bool
@@ -278,16 +318,15 @@ send_non_convert_fields(THD *thd,List<Item> &list,uint flag)
List_iterator_fast<Item> it(list);
Item *item;
char buff[80];
-
+
String tmp((char*) buff,sizeof(buff),default_charset_info);
String *res,*packet= &thd->packet;
-
+
while ((item=it++))
{
char *pos;
Send_field field;
item->make_field(&field);
-
packet->length(0);
if (thd->client_capabilities & CLIENT_PROTOCOL_41)
@@ -307,7 +346,7 @@ send_non_convert_fields(THD *thd,List<Item> &list,uint flag)
packet->realloc(packet->length()+10))
return 1;
}
-
+
pos= (char*) packet->ptr()+packet->length();
if (!(thd->client_capabilities & CLIENT_LONG_FLAG))
@@ -340,23 +379,35 @@ send_non_convert_fields(THD *thd,List<Item> &list,uint flag)
return 0;
}
-/******************************************************************************
-** Send name and type of result to client.
-** Sum fields has table name empty and field_name.
-** flag is a bit mask with the following functions:
-** 1 send number of rows
-** 2 send default values
-** 4 Don't convert field names
-******************************************************************************/
+
+/*
+ Send name and type of result to client.
+
+ SYNOPSIS
+ send_fields()
+ THD Thread data object
+ list List of items to send to client
+ convert object used to convertation to another character set
+ flag Bit mask with the following functions:
+ 1 send number of rows
+ 2 send default values
+ 4 Don't convert field names
+
+ DESCRIPTION
+ Sum fields has table name empty and field_name.
+ Uses send_fields_convert() and send_fields() depending on
+ if we have an active character set convert or not.
+
+ RETURN VALUES
+ 0 ok
+ 1 Error (Note that in this case the error is not sent to the client)
+*/
bool
-send_fields(THD *thd,List<Item> &list,uint flag)
+send_fields(THD *thd, List<Item> &list, uint flag)
{
- List_iterator_fast<Item> it(list);
- char buff[80];
CONVERT *convert= (flag & 4) ? (CONVERT*) 0 : thd->convert_set;
-
- String tmp((char*) buff,sizeof(buff),default_charset_info);
+ DBUG_ENTER("send_fields");
if (thd->fatal_error) // We have got an error
goto err;
@@ -367,20 +418,24 @@ send_fields(THD *thd,List<Item> &list,uint flag)
(void) my_net_write(&thd->net, buff,(uint) (pos-buff));
}
- /* Avoid check conditions on convert() for each field
- by having two diffrent functions
+ /*
+ Avoid check conditions on convert() for each field
+ by having two different functions
*/
- if (convert && send_convert_fields(thd,list,convert,flag))
- goto err;
-
- else if(send_non_convert_fields(thd,list,flag))
+ if (convert)
+ {
+ if (send_convert_fields(thd, list, convert, flag))
+ goto err;
+ }
+ else if (send_non_convert_fields(thd, list, flag))
goto err;
send_eof(&thd->net);
return 0;
+
err:
send_error(&thd->net,ER_OUT_OF_RESOURCES); /* purecov: inspected */
- return 1; /* purecov: inspected */
+ DBUG_RETURN(1); /* purecov: inspected */
}
@@ -396,10 +451,21 @@ void intern_close_table(TABLE *table)
VOID(closefrm(table)); // close file
}
+/*
+ Remove table from the open table cache
+
+ SYNOPSIS
+ free_cache_entry()
+ table Table to remove
+
+ NOTE
+ We need to have a lock on LOCK_open when calling this
+*/
static void free_cache_entry(TABLE *table)
{
DBUG_ENTER("free_cache_entry");
+ safe_mutex_assert_owner(&LOCK_open);
intern_close_table(table);
if (!table->in_use)
@@ -546,6 +612,7 @@ void close_thread_tables(THD *thd, bool locked)
/* VOID(pthread_sigmask(SIG_SETMASK,&thd->block_signals,NULL)); */
if (!locked)
VOID(pthread_mutex_lock(&LOCK_open));
+ safe_mutex_assert_owner(&LOCK_open);
DBUG_PRINT("info", ("thd->open_tables=%p", thd->open_tables));
@@ -671,12 +738,10 @@ void close_temporary_tables(THD *thd)
}
if (query && found_user_tables && mysql_bin_log.is_open())
{
- uint save_query_len = thd->query_length;
- *--end = 0; // Remove last ','
- thd->query_length = (uint)(end-query);
- Query_log_event qinfo(thd, query);
+ /* The -1 is to remove last ',' */
+ Query_log_event qinfo(thd, query, (ulong)(end-query)-1);
+ qinfo.error_code=0;
mysql_bin_log.write(&qinfo);
- thd->query_length = save_query_len;
}
thd->temporary_tables=0;
}
@@ -789,11 +854,13 @@ TABLE *unlink_open_table(THD *thd, TABLE *list, TABLE *find)
/*
When we call the following function we must have a lock on
- LOCK_OPEN ; This lock will be unlocked on return.
+ LOCK_open ; This lock will be unlocked on return.
*/
void wait_for_refresh(THD *thd)
{
+ safe_mutex_assert_owner(&LOCK_open);
+
/* Wait until the current table is up to date */
const char *proc_info;
thd->mysys_var->current_mutex= &LOCK_open;
@@ -811,6 +878,7 @@ void wait_for_refresh(THD *thd)
pthread_mutex_unlock(&thd->mysys_var->mutex);
}
+
TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table_list)
{
DBUG_ENTER("reopen_name_locked_table");
@@ -827,7 +895,7 @@ TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table_list)
key_length=(uint) (strmov(strmov(key,db)+1,table_name)-key)+1;
pthread_mutex_lock(&LOCK_open);
- if (open_unireg_entry(thd, table, db, table_name, table_name, 1) ||
+ if (open_unireg_entry(thd, table, db, table_name, table_name) ||
!(table->table_cache_key =memdup_root(&table->mem_root,(char*) key,
key_length)))
{
@@ -849,7 +917,8 @@ TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table_list)
table->const_table=0;
table->outer_join=table->null_row=table->maybe_null=0;
table->status=STATUS_NO_RECORD;
- table->keys_in_use_for_query=table->used_keys= table->keys_in_use;
+ table->keys_in_use_for_query= table->keys_in_use;
+ table->used_keys= table->keys_for_keyread;
DBUG_RETURN(table);
}
@@ -959,8 +1028,11 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
/* make a new table */
if (!(table=(TABLE*) my_malloc(sizeof(*table),MYF(MY_WME))))
+ {
+ VOID(pthread_mutex_unlock(&LOCK_open));
DBUG_RETURN(NULL);
- if (open_unireg_entry(thd, table,db,table_name,alias,1) ||
+ }
+ if (open_unireg_entry(thd, table,db,table_name,alias) ||
!(table->table_cache_key=memdup_root(&table->mem_root,(char*) key,
key_length)))
{
@@ -1003,7 +1075,8 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
table->const_table=0;
table->outer_join=table->null_row=table->maybe_null=0;
table->status=STATUS_NO_RECORD;
- table->keys_in_use_for_query=table->used_keys= table->keys_in_use;
+ table->keys_in_use_for_query= table->keys_in_use;
+ table->used_keys= table->keys_for_keyread;
DBUG_ASSERT(table->key_read == 0);
DBUG_RETURN(table);
}
@@ -1048,9 +1121,9 @@ bool reopen_table(TABLE *table,bool locked)
#endif
if (!locked)
VOID(pthread_mutex_lock(&LOCK_open));
+ safe_mutex_assert_owner(&LOCK_open);
- if (open_unireg_entry(current_thd,&tmp,db,table_name,table->table_name,
- locked))
+ if (open_unireg_entry(current_thd,&tmp,db,table_name,table->table_name))
goto end;
free_io_cache(table);
@@ -1069,7 +1142,8 @@ bool reopen_table(TABLE *table,bool locked)
tmp.null_row= table->null_row;
tmp.maybe_null= table->maybe_null;
tmp.status= table->status;
- tmp.keys_in_use_for_query=tmp.used_keys=tmp.keys_in_use;
+ tmp.keys_in_use_for_query= tmp.keys_in_use;
+ tmp.used_keys= tmp.keys_for_keyread;
/* Get state */
tmp.key_length= table->key_length;
@@ -1138,6 +1212,8 @@ bool close_data_tables(THD *thd,const char *db, const char *table_name)
bool reopen_tables(THD *thd,bool get_locks,bool in_refresh)
{
DBUG_ENTER("reopen_tables");
+ safe_mutex_assert_owner(&LOCK_open);
+
if (!thd->open_tables)
DBUG_RETURN(0);
@@ -1288,7 +1364,6 @@ bool wait_for_tables(THD *thd)
/* Now we can open all tables without any interference */
thd->proc_info="Reopen tables";
result=reopen_tables(thd,0,0);
-
}
pthread_mutex_unlock(&LOCK_open);
thd->proc_info=0;
@@ -1353,7 +1428,7 @@ void abort_locked_tables(THD *thd,const char *db, const char *table_name)
*/
static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
- const char *name, const char *alias, bool locked)
+ const char *name, const char *alias)
{
char path[FN_REFLEN];
int error;
@@ -1373,21 +1448,17 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
table_list.db=(char*) db;
table_list.name=(char*) name;
table_list.next=0;
- if (!locked)
- pthread_mutex_lock(&LOCK_open);
+ safe_mutex_assert_owner(&LOCK_open);
+
if ((error=lock_table_name(thd,&table_list)))
{
if (error < 0)
{
- if (!locked)
- pthread_mutex_unlock(&LOCK_open);
goto err;
}
if (wait_for_locked_table_names(thd,&table_list))
{
unlock_table_name(thd,&table_list);
- if (!locked)
- pthread_mutex_unlock(&LOCK_open);
goto err;
}
}
@@ -1417,9 +1488,9 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
thd->net.last_error[0]=0; // Clear error message
thd->net.last_errno=0;
}
- if (locked)
- pthread_mutex_lock(&LOCK_open); // Get back original lock
+ pthread_mutex_lock(&LOCK_open);
unlock_table_name(thd,&table_list);
+
if (error)
goto err;
}
@@ -1478,9 +1549,9 @@ int open_tables(THD *thd,TABLE_LIST *start)
}
}
*prev_table=0;
+ pthread_mutex_unlock(&LOCK_open);
if (found)
VOID(pthread_cond_broadcast(&COND_refresh)); // Signal to refresh
- pthread_mutex_unlock(&LOCK_open);
goto restart;
}
result= -1; // Fatal error
@@ -1698,7 +1769,7 @@ Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length,
{
field->query_id=thd->query_id;
table->used_fields++;
- table->used_keys&=field->part_of_key;
+ table->used_keys&= field->part_of_key;
}
else
thd->dupp_field=field;
@@ -1905,7 +1976,8 @@ bool setup_tables(TABLE_LIST *tables)
table->const_table=0;
table->outer_join=table->null_row=0;
table->status=STATUS_NO_RECORD;
- table->keys_in_use_for_query=table->used_keys= table->keys_in_use;
+ table->keys_in_use_for_query= table->keys_in_use;
+ table->used_keys= table->keys_for_keyread;
table->maybe_null=test(table->outer_join=table_list->outer_join);
table->tablenr=tablenr;
table->map= (table_map) 1 << tablenr;
@@ -1995,7 +2067,7 @@ insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name,
if (field->query_id == thd->query_id)
thd->dupp_field=field;
field->query_id=thd->query_id;
- table->used_keys&=field->part_of_key;
+ table->used_keys&= field->part_of_key;
}
/* All fields are used */
table->used_fields=table->fields;
@@ -2184,6 +2256,7 @@ int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
DBUG_ENTER("mysql_create_index");
bzero((char*) &create_info,sizeof(create_info));
create_info.db_type=DB_TYPE_DEFAULT;
+ /* TODO: Fix to use database character set */
create_info.table_charset=default_charset_info;
DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name,
&create_info, table_list,
@@ -2322,6 +2395,7 @@ int setup_ftfuncs(THD *thd)
return 0;
}
+
int init_ftfuncs(THD *thd, bool no_order)
{
if (thd->lex.select->ftfunc_list.elements)
@@ -2332,9 +2406,7 @@ int init_ftfuncs(THD *thd, bool no_order)
thd->proc_info="FULLTEXT initialization";
while ((ifm=li++))
- {
ifm->init_search(no_order);
- }
}
return 0;
}