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.cc338
1 files changed, 67 insertions, 271 deletions
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 870c341c148..6bbec63c258 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -19,11 +19,11 @@
#include "mysql_priv.h"
#include "sql_acl.h"
+#include "sql_select.h"
#include <m_ctype.h>
#include <my_dir.h>
#include <hash.h>
#include <nisam.h>
-#include <assert.h>
#ifdef __WIN__
#include <io.h>
#endif
@@ -195,251 +195,6 @@ OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *wild)
DBUG_RETURN(open_list);
}
-
-/*
- 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
-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_convert_fields");
-
- while ((item=it++))
- {
- char *pos;
- Send_field field;
- item->make_field(&field);
- packet->length(0);
-
- if (thd->client_capabilities & CLIENT_PROTOCOL_41)
- {
- if (convert->store(packet,field.db_name,
- (uint) strlen(field.db_name)) ||
- convert->store(packet,field.table_name,
- (uint) strlen(field.table_name)) ||
- convert->store(packet,field.org_table_name,
- (uint) strlen(field.org_table_name)) ||
- convert->store(packet,field.col_name,
- (uint) strlen(field.col_name)) ||
- convert->store(packet,field.org_col_name,
- (uint) strlen(field.org_col_name)) ||
- packet->realloc(packet->length()+10))
- goto err;
- }
- else
- {
- if (convert->store(packet,field.table_name,
- (uint) strlen(field.table_name)) ||
- convert->store(packet,field.col_name,
- (uint) strlen(field.col_name)) ||
- packet->realloc(packet->length()+10))
- goto err;
- }
- pos= (char*) packet->ptr()+packet->length();
-
- if (!(thd->client_capabilities & CLIENT_LONG_FLAG))
- {
- packet->length(packet->length()+9);
- pos[0]=3; int3store(pos+1,field.length);
- pos[4]=1; pos[5]=field.type;
- pos[6]=2; pos[7]=(char) field.flags; pos[8]= (char) field.decimals;
- }
- else
- {
- packet->length(packet->length()+10);
- pos[0]=3; int3store(pos+1,field.length);
- pos[4]=1; pos[5]=field.type;
- pos[6]=3; int2store(pos+7,field.flags); pos[9]= (char) field.decimals;
- }
- if (flag & 2)
- { // Send default value
- if (!(res=item->val_str(&tmp)))
- {
- if (net_store_null(packet))
- goto err;
- }
- 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 */
- }
- DBUG_RETURN(0);
-
-err:
- DBUG_RETURN(1);
-}
-
-
-/*
- 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
-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)
- {
- if (net_store_data(packet,field.db_name) ||
- net_store_data(packet,field.table_name) ||
- net_store_data(packet,field.org_table_name) ||
- net_store_data(packet,field.col_name) ||
- net_store_data(packet,field.org_col_name) ||
- packet->realloc(packet->length()+10))
- return 1;
- }
- else
- {
- if (net_store_data(packet,field.table_name) ||
- net_store_data(packet,field.col_name) ||
- packet->realloc(packet->length()+10))
- return 1;
- }
-
- pos= (char*) packet->ptr()+packet->length();
-
- if (!(thd->client_capabilities & CLIENT_LONG_FLAG))
- {
- packet->length(packet->length()+9);
- pos[0]=3; int3store(pos+1,field.length);
- pos[4]=1; pos[5]=field.type;
- pos[6]=2; pos[7]=(char) field.flags; pos[8]= (char) field.decimals;
- }
- else
- {
- packet->length(packet->length()+10);
- pos[0]=3; int3store(pos+1,field.length);
- pos[4]=1; pos[5]=field.type;
- pos[6]=3; int2store(pos+7,field.flags); pos[9]= (char) field.decimals;
- }
- if (flag & 2)
- { // Send default value
- if (!(res=item->val_str(&tmp)))
- {
- if (net_store_null(packet))
- return 1;
- }
- else if (net_store_data(packet,res->ptr(),res->length()))
- return 1;
- }
- if (my_net_write(&thd->net, (char*) packet->ptr(),packet->length()))
- break;
- }
- return 0;
-}
-
-
-/*
- 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)
-{
- char buff[9]; // Big enough for store_length
- CONVERT *convert= (flag & 4) ? (CONVERT*) 0 : thd->variables.convert_set;
- DBUG_ENTER("send_fields");
-
- if (thd->fatal_error) // We have got an error
- goto err;
-
- if (flag & 1)
- { // Packet with number of elements
- char *pos=net_store_length(buff, (uint) list.elements);
- (void) my_net_write(&thd->net, buff,(uint) (pos-buff));
- }
-
- /*
- Avoid check conditions on convert() for each field
- by having two different functions
- */
- 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);
- DBUG_RETURN(0);
-
-err:
- send_error(thd,ER_OUT_OF_RESOURCES); /* purecov: inspected */
- DBUG_RETURN(1); /* purecov: inspected */
-}
-
-
/*****************************************************************************
* Functions to free open table cache
****************************************************************************/
@@ -485,6 +240,7 @@ static void free_cache_entry(TABLE *table)
DBUG_VOID_RETURN;
}
+/* Free resources allocated by filesort() and read_record() */
void free_io_cache(TABLE *table)
{
@@ -551,7 +307,8 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
close_old_data_files(thd,thd->open_tables,1,1);
bool found=1;
/* Wait until all threads has closed all the tables we had locked */
- DBUG_PRINT("info", ("Waiting for others threads to close their open tables"));
+ DBUG_PRINT("info",
+ ("Waiting for others threads to close their open tables"));
while (found && ! thd->killed)
{
found=0;
@@ -592,12 +349,40 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
}
-/* Put all tables used by thread in free list */
+/*
+ Close all tables used by thread
-void close_thread_tables(THD *thd, bool locked)
+ SYNOPSIS
+ close_thread_tables()
+ thd Thread handler
+ lock_in_use Set to 1 (0 = default) if caller has a lock on
+ LOCK_open
+ skip_derived Set to 1 (0 = default) if we should not free derived
+ tables.
+
+ IMPLEMENTATION
+ Unlocks tables and frees derived tables.
+ Put all normal tables used by thread in free list.
+*/
+
+void close_thread_tables(THD *thd, bool lock_in_use, bool skip_derived)
{
DBUG_ENTER("close_thread_tables");
+ if (thd->derived_tables && !skip_derived)
+ {
+ TABLE *table, *next;
+ /*
+ Close all derived tables generated from questions like
+ SELECT * from (select * from t1))
+ */
+ for (table= thd->derived_tables ; table ; table= next)
+ {
+ next= table->next;
+ free_tmp_table(thd, table);
+ }
+ thd->derived_tables= 0;
+ }
if (thd->locked_tables)
{
ha_commit_stmt(thd); // If select statement
@@ -608,10 +393,11 @@ void close_thread_tables(THD *thd, bool locked)
if (thd->lock)
{
- mysql_unlock_tables(thd, thd->lock); thd->lock=0;
+ mysql_unlock_tables(thd, thd->lock);
+ thd->lock=0;
}
/* VOID(pthread_sigmask(SIG_SETMASK,&thd->block_signals,NULL)); */
- if (!locked)
+ if (!lock_in_use)
VOID(pthread_mutex_lock(&LOCK_open));
safe_mutex_assert_owner(&LOCK_open);
@@ -630,7 +416,7 @@ void close_thread_tables(THD *thd, bool locked)
/* Tell threads waiting for refresh that something has happened */
VOID(pthread_cond_broadcast(&COND_refresh));
}
- if (!locked)
+ if (!lock_in_use)
VOID(pthread_mutex_unlock(&LOCK_open));
/* VOID(pthread_sigmask(SIG_SETMASK,&thd->signals,NULL)); */
DBUG_VOID_RETURN;
@@ -798,7 +584,7 @@ TABLE **find_temporary_table(THD *thd, const char *db, const char *table_name)
uint key_length= (uint) (strmov(strmov(key,db)+1,table_name)-key)+1;
TABLE *table,**prev;
- int4store(key+key_length,thd->slave_proxy_id);
+ int4store(key+key_length,thd->variables.pseudo_thread_id);
key_length += 4;
prev= &thd->temporary_tables;
@@ -838,7 +624,7 @@ bool rename_temporary_table(THD* thd, TABLE *table, const char *db,
(strmov((table->real_name=strmov(table->table_cache_key=key,
db)+1),
table_name) - table->table_cache_key)+1;
- int4store(key+table->key_length,thd->slave_proxy_id);
+ int4store(key+table->key_length,thd->variables.pseudo_thread_id);
table->key_length += 4;
return 0;
}
@@ -960,7 +746,7 @@ TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table_list)
table->tablenr=thd->current_tablenr++;
table->used_fields=0;
table->const_table=0;
- table->outer_join=table->null_row=table->maybe_null=0;
+ table->outer_join= table->null_row= table->maybe_null= table->force_index= 0;
table->status=STATUS_NO_RECORD;
table->keys_in_use_for_query= table->keys_in_use;
table->used_keys= table->keys_for_keyread;
@@ -992,7 +778,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
if (thd->killed)
DBUG_RETURN(0);
key_length= (uint) (strmov(strmov(key,db)+1,table_name)-key)+1;
- int4store(key + key_length, thd->slave_proxy_id);
+ int4store(key + key_length, thd->variables.pseudo_thread_id);
for (table=thd->temporary_tables; table ; table=table->next)
{
@@ -1006,6 +792,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
DBUG_RETURN(0);
}
table->query_id=thd->query_id;
+ thd->lex.tmp_table_used= 1;
goto reset;
}
}
@@ -1118,7 +905,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
table->tablenr=thd->current_tablenr++;
table->used_fields=0;
table->const_table=0;
- table->outer_join=table->null_row=table->maybe_null=0;
+ table->outer_join= table->null_row= table->maybe_null= table->force_index= 0;
table->status=STATUS_NO_RECORD;
table->keys_in_use_for_query= table->keys_in_use;
table->used_keys= table->keys_for_keyread;
@@ -1189,6 +976,7 @@ bool reopen_table(TABLE *table,bool locked)
tmp.status= table->status;
tmp.keys_in_use_for_query= tmp.keys_in_use;
tmp.used_keys= tmp.keys_for_keyread;
+ tmp.force_index= tmp.force_index;
/* Get state */
tmp.key_length= table->key_length;
@@ -1806,7 +1594,7 @@ TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
+1), table_name)
- tmp_table->table_cache_key)+1;
int4store(tmp_table->table_cache_key + tmp_table->key_length,
- thd->slave_proxy_id);
+ thd->variables.pseudo_thread_id);
tmp_table->key_length += 4;
if (link_in_list)
@@ -1898,6 +1686,7 @@ const Field *not_found_field= (Field*) 0x1;
thd - pointer to current thread structure
item - field item that should be found
tables - tables for scaning
+ where - table where field found will be returned via this parameter
report_error - if FALSE then do not report error if item not found and
return not_found_field;
@@ -1911,7 +1700,7 @@ const Field *not_found_field= (Field*) 0x1;
Field *
find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
- bool report_error)
+ TABLE_LIST **where, bool report_error)
{
Field *found=0;
const char *db=item->db_name;
@@ -1932,6 +1721,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
grant_option && !thd->master_access,1);
if (find)
{
+ (*where)= tables;
if (find == WRONG_GRANT)
return (Field*) 0;
if (db || !thd->where)
@@ -1951,19 +1741,15 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
if (!found_table && report_error)
{
char buff[NAME_LEN*2+1];
- if (db)
+ if (db && db[0])
{
strxnmov(buff,sizeof(buff)-1,db,".",table_name,NullS);
table_name=buff;
}
if (report_error)
{
- if (thd->lex.current_select->get_master()->order_list.elements)
- my_printf_error(ER_TABLENAME_NOT_ALLOWED_HERE, ER(ER_TABLENAME_NOT_ALLOWED_HERE),
- MYF(0), table_name, thd->where);
- else
- my_printf_error(ER_UNKNOWN_TABLE, ER(ER_UNKNOWN_TABLE), MYF(0),
- table_name, thd->where);
+ my_printf_error(ER_UNKNOWN_TABLE, ER(ER_UNKNOWN_TABLE), MYF(0),
+ table_name, thd->where);
}
else
return (Field*) not_found_field;
@@ -1979,6 +1765,14 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
bool allow_rowid= tables && !tables->next; // Only one table
for (; tables ; tables=tables->next)
{
+ if (!tables->table)
+ {
+ if (report_error)
+ my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),MYF(0),
+ item->full_name(),thd->where);
+ return (Field*) not_found_field;
+ }
+
Field *field=find_field_in_table(thd,tables->table,name,length,
grant_option &&
!thd->master_access, allow_rowid);
@@ -1986,6 +1780,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
{
if (field == WRONG_GRANT)
return (Field*) 0;
+ (*where)= tables;
if (found)
{
if (!thd->where) // Returns first found
@@ -2158,8 +1953,8 @@ int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
for (uint i= 0; (item= it++); i++)
{
- if (item->check_cols(1) ||
- item->fix_fields(thd, tables, it.ref()))
+ if (item->fix_fields(thd, tables, it.ref()) ||
+ item->check_cols(1))
DBUG_RETURN(-1); /* purecov: inspected */
item= *(it.ref()); //Item can be chenged in fix fields
if (ref_pointer_array)
@@ -2196,6 +1991,7 @@ bool setup_tables(TABLE_LIST *tables)
table->maybe_null=test(table->outer_join=table_list->outer_join);
table->tablenr=tablenr;
table->map= (table_map) 1 << tablenr;
+ table->force_index= table_list->force_index;
if (table_list->use_index)
{
key_map map= get_key_map_from_key_list(table,
@@ -2318,7 +2114,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
if (*conds)
{
thd->where="where clause";
- if ((*conds)->check_cols(1) || (*conds)->fix_fields(thd, tables, conds))
+ if ((*conds)->fix_fields(thd, tables, conds) || (*conds)->check_cols(1))
DBUG_RETURN(1);
}
@@ -2329,8 +2125,8 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
{
/* Make a join an a expression */
thd->where="on clause";
- if (table->on_expr->check_cols(1) ||
- table->on_expr->fix_fields(thd, tables, &table->on_expr))
+ if (table->on_expr->fix_fields(thd, tables, &table->on_expr) ||
+ table->on_expr->check_cols(1))
DBUG_RETURN(1);
thd->cond_count++;