mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Merge mysqldev@production.mysql.com:my/mysql-5.0-release
into mysql.com:/opt/local/work/mysql-5.0-root
This commit is contained in:
@ -23,6 +23,7 @@
|
||||
|
||||
#include "mysql_priv.h"
|
||||
#include "sql_select.h"
|
||||
#include "sql_cursor.h"
|
||||
|
||||
#include <m_ctype.h>
|
||||
#include <hash.h>
|
||||
@ -107,20 +108,15 @@ static bool const_expression_in_where(COND *conds,Item *item, Item **comp_item);
|
||||
static bool open_tmp_table(TABLE *table);
|
||||
static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
|
||||
ulong options);
|
||||
static Next_select_func setup_end_select_func(JOIN *join);
|
||||
static int do_select(JOIN *join,List<Item> *fields,TABLE *tmp_table,
|
||||
Procedure *proc);
|
||||
|
||||
static enum_nested_loop_state
|
||||
sub_select_cache(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
|
||||
static enum_nested_loop_state
|
||||
evaluate_join_record(JOIN *join, JOIN_TAB *join_tab,
|
||||
int error, my_bool *report_error);
|
||||
static enum_nested_loop_state
|
||||
evaluate_null_complemented_join_record(JOIN *join, JOIN_TAB *join_tab);
|
||||
static enum_nested_loop_state
|
||||
sub_select(JOIN *join,JOIN_TAB *join_tab, bool end_of_records);
|
||||
static enum_nested_loop_state
|
||||
flush_cached_records(JOIN *join, JOIN_TAB *join_tab, bool skip_last);
|
||||
static enum_nested_loop_state
|
||||
end_send(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
|
||||
@ -1716,262 +1712,6 @@ JOIN::destroy()
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
|
||||
/************************* Cursor ******************************************/
|
||||
|
||||
Cursor::Cursor(THD *thd)
|
||||
:Query_arena(&main_mem_root, INITIALIZED),
|
||||
join(0), unit(0),
|
||||
protocol(thd),
|
||||
close_at_commit(FALSE)
|
||||
{
|
||||
/* We will overwrite it at open anyway. */
|
||||
init_sql_alloc(&main_mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
|
||||
thr_lock_owner_init(&lock_id, &thd->lock_info);
|
||||
bzero((void*) ht_info, sizeof(ht_info));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Cursor::init_from_thd(THD *thd)
|
||||
{
|
||||
Engine_info *info;
|
||||
/*
|
||||
We need to save and reset thd->mem_root, otherwise it'll be freed
|
||||
later in mysql_parse.
|
||||
|
||||
We can't just change the thd->mem_root here as we want to keep the
|
||||
things that are already allocated in thd->mem_root for Cursor::fetch()
|
||||
*/
|
||||
main_mem_root= *thd->mem_root;
|
||||
state= thd->stmt_arena->state;
|
||||
/* Allocate new memory root for thd */
|
||||
init_sql_alloc(thd->mem_root,
|
||||
thd->variables.query_alloc_block_size,
|
||||
thd->variables.query_prealloc_size);
|
||||
|
||||
/*
|
||||
The same is true for open tables and lock: save tables and zero THD
|
||||
pointers to prevent table close in close_thread_tables (This is a part
|
||||
of the temporary solution to make cursors work with minimal changes to
|
||||
the current source base).
|
||||
*/
|
||||
derived_tables= thd->derived_tables;
|
||||
open_tables= thd->open_tables;
|
||||
lock= thd->lock;
|
||||
query_id= thd->query_id;
|
||||
free_list= thd->free_list;
|
||||
change_list= thd->change_list;
|
||||
reset_thd(thd);
|
||||
/* Now we have an active cursor and can cause a deadlock */
|
||||
thd->lock_info.n_cursors++;
|
||||
|
||||
close_at_commit= FALSE; /* reset in case we're reusing the cursor */
|
||||
info= &ht_info[0];
|
||||
for (handlerton **pht= thd->transaction.stmt.ht; *pht; pht++)
|
||||
{
|
||||
const handlerton *ht= *pht;
|
||||
close_at_commit|= test(ht->flags & HTON_CLOSE_CURSORS_AT_COMMIT);
|
||||
if (ht->create_cursor_read_view)
|
||||
{
|
||||
info->ht= ht;
|
||||
info->read_view= (ht->create_cursor_read_view)();
|
||||
++info;
|
||||
}
|
||||
}
|
||||
/*
|
||||
XXX: thd->locked_tables is not changed.
|
||||
What problems can we have with it if cursor is open?
|
||||
TODO: must be fixed because of the prelocked mode.
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Cursor::reset_thd(THD *thd)
|
||||
{
|
||||
thd->derived_tables= 0;
|
||||
thd->open_tables= 0;
|
||||
thd->lock= 0;
|
||||
thd->free_list= 0;
|
||||
thd->change_list.empty();
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Cursor::open(JOIN *join_arg)
|
||||
{
|
||||
join= join_arg;
|
||||
THD *thd= join->thd;
|
||||
/* First non-constant table */
|
||||
JOIN_TAB *join_tab= join->join_tab + join->const_tables;
|
||||
DBUG_ENTER("Cursor::open");
|
||||
|
||||
/*
|
||||
Send fields description to the client; server_status is sent
|
||||
in 'EOF' packet, which ends send_fields().
|
||||
*/
|
||||
thd->server_status|= SERVER_STATUS_CURSOR_EXISTS;
|
||||
join->result->send_fields(*join->fields, Protocol::SEND_NUM_ROWS);
|
||||
::send_eof(thd);
|
||||
thd->server_status&= ~SERVER_STATUS_CURSOR_EXISTS;
|
||||
|
||||
/* Prepare JOIN for reading rows. */
|
||||
join->tmp_table= 0;
|
||||
join->join_tab[join->tables-1].next_select= setup_end_select_func(join);
|
||||
join->send_records= 0;
|
||||
join->fetch_limit= join->unit->offset_limit_cnt;
|
||||
|
||||
/* Disable JOIN CACHE as it is not working with cursors yet */
|
||||
for (JOIN_TAB *tab= join_tab;
|
||||
tab != join->join_tab + join->tables - 1;
|
||||
tab++)
|
||||
{
|
||||
if (tab->next_select == sub_select_cache)
|
||||
tab->next_select= sub_select;
|
||||
}
|
||||
|
||||
DBUG_ASSERT(join_tab->table->reginfo.not_exists_optimize == 0);
|
||||
DBUG_ASSERT(join_tab->not_used_in_distinct == 0);
|
||||
/*
|
||||
null_row is set only if row not found and it's outer join: should never
|
||||
happen for the first table in join_tab list
|
||||
*/
|
||||
DBUG_ASSERT(join_tab->table->null_row == 0);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
DESCRIPTION
|
||||
Fetch next num_rows rows from the cursor and sent them to the client
|
||||
PRECONDITION:
|
||||
Cursor is open
|
||||
RETURN VALUES:
|
||||
none, this function will send error or OK to network if necessary.
|
||||
*/
|
||||
|
||||
void
|
||||
Cursor::fetch(ulong num_rows)
|
||||
{
|
||||
THD *thd= join->thd;
|
||||
JOIN_TAB *join_tab= join->join_tab + join->const_tables;
|
||||
enum_nested_loop_state error= NESTED_LOOP_OK;
|
||||
Query_arena backup_arena;
|
||||
Engine_info *info;
|
||||
DBUG_ENTER("Cursor::fetch");
|
||||
DBUG_PRINT("enter",("rows: %lu", num_rows));
|
||||
|
||||
DBUG_ASSERT(thd->derived_tables == 0 && thd->open_tables == 0 &&
|
||||
thd->lock == 0);
|
||||
|
||||
thd->derived_tables= derived_tables;
|
||||
thd->open_tables= open_tables;
|
||||
thd->lock= lock;
|
||||
thd->query_id= query_id;
|
||||
thd->change_list= change_list;
|
||||
/* save references to memory, allocated during fetch */
|
||||
thd->set_n_backup_active_arena(this, &backup_arena);
|
||||
|
||||
for (info= ht_info; info->read_view ; info++)
|
||||
(info->ht->set_cursor_read_view)(info->read_view);
|
||||
|
||||
join->fetch_limit+= num_rows;
|
||||
|
||||
error= sub_select(join, join_tab, 0);
|
||||
if (error == NESTED_LOOP_OK || error == NESTED_LOOP_NO_MORE_ROWS)
|
||||
error= sub_select(join,join_tab,1);
|
||||
if (error == NESTED_LOOP_QUERY_LIMIT)
|
||||
error= NESTED_LOOP_OK; /* select_limit used */
|
||||
if (error == NESTED_LOOP_CURSOR_LIMIT)
|
||||
join->resume_nested_loop= TRUE;
|
||||
|
||||
#ifdef USING_TRANSACTIONS
|
||||
ha_release_temporary_latches(thd);
|
||||
#endif
|
||||
/* Grab free_list here to correctly free it in close */
|
||||
thd->restore_active_arena(this, &backup_arena);
|
||||
|
||||
for (info= ht_info; info->read_view; info++)
|
||||
(info->ht->set_cursor_read_view)(0);
|
||||
|
||||
if (error == NESTED_LOOP_CURSOR_LIMIT)
|
||||
{
|
||||
/* Fetch limit worked, possibly more rows are there */
|
||||
thd->server_status|= SERVER_STATUS_CURSOR_EXISTS;
|
||||
::send_eof(thd);
|
||||
thd->server_status&= ~SERVER_STATUS_CURSOR_EXISTS;
|
||||
change_list= thd->change_list;
|
||||
reset_thd(thd);
|
||||
}
|
||||
else
|
||||
{
|
||||
close(TRUE);
|
||||
if (error == NESTED_LOOP_OK)
|
||||
{
|
||||
thd->server_status|= SERVER_STATUS_LAST_ROW_SENT;
|
||||
::send_eof(thd);
|
||||
thd->server_status&= ~SERVER_STATUS_LAST_ROW_SENT;
|
||||
}
|
||||
else if (error != NESTED_LOOP_KILLED)
|
||||
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
|
||||
}
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Cursor::close(bool is_active)
|
||||
{
|
||||
THD *thd= join->thd;
|
||||
DBUG_ENTER("Cursor::close");
|
||||
|
||||
/*
|
||||
In case of UNIONs JOIN is freed inside of unit->cleanup(),
|
||||
otherwise in select_lex->cleanup().
|
||||
*/
|
||||
if (unit)
|
||||
(void) unit->cleanup();
|
||||
else
|
||||
(void) join->select_lex->cleanup();
|
||||
|
||||
for (Engine_info *info= ht_info; info->read_view; info++)
|
||||
{
|
||||
(info->ht->close_cursor_read_view)(info->read_view);
|
||||
info->read_view= 0;
|
||||
info->ht= 0;
|
||||
}
|
||||
|
||||
if (is_active)
|
||||
close_thread_tables(thd);
|
||||
else
|
||||
{
|
||||
/* XXX: Another hack: closing tables used in the cursor */
|
||||
DBUG_ASSERT(lock || open_tables || derived_tables);
|
||||
|
||||
TABLE *tmp_derived_tables= thd->derived_tables;
|
||||
MYSQL_LOCK *tmp_lock= thd->lock;
|
||||
|
||||
thd->open_tables= open_tables;
|
||||
thd->derived_tables= derived_tables;
|
||||
thd->lock= lock;
|
||||
close_thread_tables(thd);
|
||||
|
||||
thd->open_tables= tmp_derived_tables;
|
||||
thd->derived_tables= tmp_derived_tables;
|
||||
thd->lock= tmp_lock;
|
||||
}
|
||||
thd->lock_info.n_cursors--; /* Decrease the number of active cursors */
|
||||
join= 0;
|
||||
unit= 0;
|
||||
free_items();
|
||||
change_list.empty();
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************/
|
||||
|
||||
/*
|
||||
An entry point to single-unit select (a select without UNION).
|
||||
|
||||
@ -2051,9 +1791,9 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (join->prepare(rref_pointer_array, tables, wild_num,
|
||||
conds, og_num, order, group, having, proc_param,
|
||||
select_lex, unit))
|
||||
if (err= join->prepare(rref_pointer_array, tables, wild_num,
|
||||
conds, og_num, order, group, having, proc_param,
|
||||
select_lex, unit))
|
||||
{
|
||||
goto err;
|
||||
}
|
||||
@ -2068,9 +1808,9 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
|
||||
DBUG_RETURN(TRUE);
|
||||
thd->proc_info="init";
|
||||
thd->used_tables=0; // Updated by setup_fields
|
||||
if (join->prepare(rref_pointer_array, tables, wild_num,
|
||||
conds, og_num, order, group, having, proc_param,
|
||||
select_lex, unit))
|
||||
if (err= join->prepare(rref_pointer_array, tables, wild_num,
|
||||
conds, og_num, order, group, having, proc_param,
|
||||
select_lex, unit))
|
||||
{
|
||||
goto err;
|
||||
}
|
||||
@ -2112,7 +1852,7 @@ err:
|
||||
if (free_join)
|
||||
{
|
||||
thd->proc_info="end";
|
||||
err= select_lex->cleanup();
|
||||
err|= select_lex->cleanup();
|
||||
DBUG_RETURN(err || thd->net.report_error);
|
||||
}
|
||||
DBUG_RETURN(join->error);
|
||||
@ -5976,7 +5716,7 @@ void JOIN::join_free(bool full)
|
||||
cleanup(full);
|
||||
|
||||
for (unit= select_lex->first_inner_unit(); unit; unit= unit->next_unit())
|
||||
for (sl= unit->first_select_in_union(); sl; sl= sl->next_select())
|
||||
for (sl= unit->first_select(); sl; sl= sl->next_select())
|
||||
{
|
||||
JOIN *join= sl->join;
|
||||
if (join)
|
||||
@ -8077,18 +7817,24 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
|
||||
if (field->maybe_null && !field->field->maybe_null())
|
||||
{
|
||||
result= create_tmp_field_from_item(thd, item, table, NULL,
|
||||
modify_item, convert_blob_length);
|
||||
modify_item, convert_blob_length);
|
||||
*from_field= field->field;
|
||||
if (result && modify_item)
|
||||
((Item_field*)item)->result_field= result;
|
||||
field->result_field= result;
|
||||
}
|
||||
else if (table_cant_handle_bit_fields && field->field->type() == FIELD_TYPE_BIT)
|
||||
else if (table_cant_handle_bit_fields && field->field->type() ==
|
||||
FIELD_TYPE_BIT)
|
||||
{
|
||||
*from_field= field->field;
|
||||
result= create_tmp_field_from_item(thd, item, table, copy_func,
|
||||
modify_item, convert_blob_length);
|
||||
if (result && modify_item)
|
||||
field->result_field= result;
|
||||
}
|
||||
else
|
||||
result= create_tmp_field_from_field(thd, (*from_field= field->field),
|
||||
item->name, table,
|
||||
modify_item ? (Item_field*) item :
|
||||
modify_item ? field :
|
||||
NULL,
|
||||
convert_blob_length);
|
||||
if (orig_type == Item::REF_ITEM && orig_modify)
|
||||
@ -8122,9 +7868,31 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
|
||||
|
||||
/*
|
||||
Create a temp table according to a field list.
|
||||
Set distinct if duplicates could be removed
|
||||
Given fields field pointers are changed to point at tmp_table
|
||||
for send_fields
|
||||
|
||||
SYNOPSIS
|
||||
create_tmp_table()
|
||||
thd thread handle
|
||||
param a description used as input to create the table
|
||||
fields list of items that will be used to define
|
||||
column types of the table (also see NOTES)
|
||||
group TODO document
|
||||
distinct should table rows be distinct
|
||||
save_sum_fields see NOTES
|
||||
select_options
|
||||
rows_limit
|
||||
table_alias possible name of the temporary table that can be used
|
||||
for name resolving; can be "".
|
||||
|
||||
DESCRIPTION
|
||||
Given field pointers are changed to point at tmp_table for
|
||||
send_fields. The table object is self contained: it's
|
||||
allocated in its own memory root, as well as Field objects
|
||||
created for table columns.
|
||||
This function will replace Item_sum items in 'fields' list with
|
||||
corresponding Item_field items, pointing at the fields in the
|
||||
temporary table, unless this was prohibited by TRUE
|
||||
value of argument save_sum_fields. The Item_field objects
|
||||
are created in THD memory root.
|
||||
*/
|
||||
|
||||
#define STRING_TOTAL_LENGTH_TO_PACK_ROWS 128
|
||||
@ -8138,6 +7906,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
|
||||
ulonglong select_options, ha_rows rows_limit,
|
||||
char *table_alias)
|
||||
{
|
||||
MEM_ROOT *mem_root_save, own_root;
|
||||
TABLE *table;
|
||||
uint i,field_count,null_count,null_pack_length;
|
||||
uint hidden_null_count, hidden_null_pack_length, hidden_field_count;
|
||||
@ -8202,29 +7971,33 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
|
||||
|
||||
field_count=param->field_count+param->func_count+param->sum_func_count;
|
||||
hidden_field_count=param->hidden_field_count;
|
||||
if (!my_multi_malloc(MYF(MY_WME),
|
||||
&table,sizeof(*table),
|
||||
®_field, sizeof(Field*)*(field_count+1),
|
||||
&blob_field, sizeof(uint)*(field_count+1),
|
||||
&from_field, sizeof(Field*)*field_count,
|
||||
©_func,sizeof(*copy_func)*(param->func_count+1),
|
||||
¶m->keyinfo,sizeof(*param->keyinfo),
|
||||
&key_part_info,
|
||||
sizeof(*key_part_info)*(param->group_parts+1),
|
||||
¶m->start_recinfo,
|
||||
sizeof(*param->recinfo)*(field_count*2+4),
|
||||
&tmpname,(uint) strlen(path)+1,
|
||||
&group_buff,group && ! using_unique_constraint ?
|
||||
param->group_length : 0,
|
||||
NullS))
|
||||
|
||||
init_sql_alloc(&own_root, TABLE_ALLOC_BLOCK_SIZE, 0);
|
||||
|
||||
if (!multi_alloc_root(&own_root,
|
||||
&table, sizeof(*table),
|
||||
®_field, sizeof(Field*) * (field_count+1),
|
||||
&blob_field, sizeof(uint)*(field_count+1),
|
||||
&from_field, sizeof(Field*)*field_count,
|
||||
©_func, sizeof(*copy_func)*(param->func_count+1),
|
||||
¶m->keyinfo, sizeof(*param->keyinfo),
|
||||
&key_part_info,
|
||||
sizeof(*key_part_info)*(param->group_parts+1),
|
||||
¶m->start_recinfo,
|
||||
sizeof(*param->recinfo)*(field_count*2+4),
|
||||
&tmpname, (uint) strlen(path)+1,
|
||||
&group_buff, group && ! using_unique_constraint ?
|
||||
param->group_length : 0,
|
||||
NullS))
|
||||
{
|
||||
bitmap_clear_bit(&temp_pool, temp_pool_slot);
|
||||
DBUG_RETURN(NULL); /* purecov: inspected */
|
||||
}
|
||||
if (!(param->copy_field=copy=new Copy_field[field_count]))
|
||||
/* Copy_field belongs to TMP_TABLE_PARAM, allocate it in THD mem_root */
|
||||
if (!(param->copy_field= copy= new (thd->mem_root) Copy_field[field_count]))
|
||||
{
|
||||
bitmap_clear_bit(&temp_pool, temp_pool_slot);
|
||||
my_free((gptr) table,MYF(0)); /* purecov: inspected */
|
||||
free_root(&own_root, MYF(0)); /* purecov: inspected */
|
||||
DBUG_RETURN(NULL); /* purecov: inspected */
|
||||
}
|
||||
param->items_to_copy= copy_func;
|
||||
@ -8234,6 +8007,11 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
|
||||
bzero((char*) table,sizeof(*table));
|
||||
bzero((char*) reg_field,sizeof(Field*)*(field_count+1));
|
||||
bzero((char*) from_field,sizeof(Field*)*field_count);
|
||||
|
||||
table->mem_root= own_root;
|
||||
mem_root_save= thd->mem_root;
|
||||
thd->mem_root= &table->mem_root;
|
||||
|
||||
table->field=reg_field;
|
||||
table->alias= table_alias;
|
||||
table->reginfo.lock_type=TL_WRITE; /* Will be updated */
|
||||
@ -8299,7 +8077,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
|
||||
Field *new_field=
|
||||
create_tmp_field(thd, table, arg, arg->type(), ©_func,
|
||||
tmp_from_field, group != 0,not_all_columns,
|
||||
group || distinct,
|
||||
distinct,
|
||||
param->convert_blob_length);
|
||||
if (!new_field)
|
||||
goto err; // Should be OOM
|
||||
@ -8310,6 +8088,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
|
||||
*blob_field++= (uint) (reg_field - table->field);
|
||||
blob_count++;
|
||||
}
|
||||
if (new_field->type() == FIELD_TYPE_BIT)
|
||||
total_uneven_bit_length+= new_field->field_length & 7;
|
||||
new_field->field_index= (uint) (reg_field - table->field);
|
||||
*(reg_field++)= new_field;
|
||||
if (new_field->real_type() == MYSQL_TYPE_STRING ||
|
||||
@ -8318,7 +8098,9 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
|
||||
string_count++;
|
||||
string_total_length+= new_field->pack_length();
|
||||
}
|
||||
thd->mem_root= mem_root_save;
|
||||
thd->change_item_tree(argp, new Item_field(new_field));
|
||||
thd->mem_root= &table->mem_root;
|
||||
if (!(new_field->flags & NOT_NULL_FLAG))
|
||||
{
|
||||
null_count++;
|
||||
@ -8343,12 +8125,16 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
|
||||
write rows to the temporary table.
|
||||
We here distinguish between UNION and multi-table-updates by the fact
|
||||
that in the later case group is set to the row pointer.
|
||||
|
||||
The test for item->marker == 4 is ensure we don't create a group-by
|
||||
key over a bit field as heap tables can't handle that.
|
||||
*/
|
||||
Field *new_field= (param->schema_table) ?
|
||||
create_tmp_field_for_schema(thd, item, table) :
|
||||
create_tmp_field(thd, table, item, type, ©_func,
|
||||
tmp_from_field, group != 0,
|
||||
not_all_columns || group != 0, 0,
|
||||
not_all_columns || group != 0,
|
||||
item->marker == 4,
|
||||
param->convert_blob_length);
|
||||
|
||||
if (!new_field)
|
||||
@ -8380,7 +8166,14 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
|
||||
*(reg_field++) =new_field;
|
||||
}
|
||||
if (!--hidden_field_count)
|
||||
{
|
||||
/*
|
||||
This was the last hidden field; Remember how many hidden fields could
|
||||
have null
|
||||
*/
|
||||
hidden_null_count=null_count;
|
||||
null_count= 0;
|
||||
}
|
||||
}
|
||||
DBUG_ASSERT(field_count >= (uint) (reg_field - table->field));
|
||||
field_count= (uint) (reg_field - table->field);
|
||||
@ -8415,8 +8208,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
|
||||
null_count++;
|
||||
}
|
||||
hidden_null_pack_length=(hidden_null_count+7)/8;
|
||||
null_pack_length= hidden_null_count +
|
||||
(null_count + total_uneven_bit_length + 7) / 8;
|
||||
null_pack_length= (hidden_null_pack_length +
|
||||
(null_count + total_uneven_bit_length + 7) / 8);
|
||||
reclength+=null_pack_length;
|
||||
if (!reclength)
|
||||
reclength=1; // Dummy select
|
||||
@ -8432,7 +8225,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
|
||||
{
|
||||
uint alloc_length=ALIGN_SIZE(reclength+MI_UNIQUE_HASH_LENGTH+1);
|
||||
table->s->rec_buff_length= alloc_length;
|
||||
if (!(table->record[0]= (byte *) my_malloc(alloc_length*3, MYF(MY_WME))))
|
||||
if (!(table->record[0]= (byte*)
|
||||
alloc_root(&table->mem_root, alloc_length*3)))
|
||||
goto err;
|
||||
table->record[1]= table->record[0]+alloc_length;
|
||||
table->s->default_values= table->record[1]+alloc_length;
|
||||
@ -8618,8 +8412,10 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
|
||||
table->s->uniques= 1;
|
||||
}
|
||||
if (!(key_part_info= (KEY_PART_INFO*)
|
||||
sql_calloc((keyinfo->key_parts)*sizeof(KEY_PART_INFO))))
|
||||
alloc_root(&table->mem_root,
|
||||
keyinfo->key_parts * sizeof(KEY_PART_INFO))))
|
||||
goto err;
|
||||
bzero((void*) key_part_info, keyinfo->key_parts * sizeof(KEY_PART_INFO));
|
||||
table->key_info=keyinfo;
|
||||
keyinfo->key_part=key_part_info;
|
||||
keyinfo->flags=HA_NOSAME | HA_NULL_ARE_EQUAL;
|
||||
@ -8667,10 +8463,15 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
|
||||
if (create_myisam_tmp_table(table,param,select_options))
|
||||
goto err;
|
||||
}
|
||||
if (!open_tmp_table(table))
|
||||
DBUG_RETURN(table);
|
||||
if (open_tmp_table(table))
|
||||
goto err;
|
||||
|
||||
err:
|
||||
thd->mem_root= mem_root_save;
|
||||
|
||||
DBUG_RETURN(table);
|
||||
|
||||
err:
|
||||
thd->mem_root= mem_root_save;
|
||||
free_tmp_table(thd,table); /* purecov: inspected */
|
||||
bitmap_clear_bit(&temp_pool, temp_pool_slot);
|
||||
DBUG_RETURN(NULL); /* purecov: inspected */
|
||||
@ -8815,11 +8616,12 @@ static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
|
||||
if (table->s->keys)
|
||||
{ // Get keys for ni_create
|
||||
bool using_unique_constraint=0;
|
||||
HA_KEYSEG *seg= (HA_KEYSEG*) sql_calloc(sizeof(*seg) *
|
||||
keyinfo->key_parts);
|
||||
HA_KEYSEG *seg= (HA_KEYSEG*) alloc_root(&table->mem_root,
|
||||
sizeof(*seg) * keyinfo->key_parts);
|
||||
if (!seg)
|
||||
goto err;
|
||||
|
||||
bzero(seg, sizeof(*seg) * keyinfo->key_parts);
|
||||
if (keyinfo->key_length >= table->file->max_key_length() ||
|
||||
keyinfo->key_parts > table->file->max_key_parts() ||
|
||||
table->s->uniques)
|
||||
@ -8916,13 +8718,14 @@ static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
|
||||
void
|
||||
free_tmp_table(THD *thd, TABLE *entry)
|
||||
{
|
||||
MEM_ROOT own_root= entry->mem_root;
|
||||
const char *save_proc_info;
|
||||
DBUG_ENTER("free_tmp_table");
|
||||
DBUG_PRINT("enter",("table: %s",entry->alias));
|
||||
|
||||
save_proc_info=thd->proc_info;
|
||||
thd->proc_info="removing tmp table";
|
||||
free_blobs(entry);
|
||||
|
||||
if (entry->file)
|
||||
{
|
||||
if (entry->db_stat)
|
||||
@ -8943,12 +8746,11 @@ free_tmp_table(THD *thd, TABLE *entry)
|
||||
/* free blobs */
|
||||
for (Field **ptr=entry->field ; *ptr ; ptr++)
|
||||
(*ptr)->free();
|
||||
my_free((gptr) entry->record[0],MYF(0));
|
||||
free_io_cache(entry);
|
||||
|
||||
bitmap_clear_bit(&temp_pool, entry->temp_pool_slot);
|
||||
|
||||
my_free((gptr) entry,MYF(0));
|
||||
free_root(&own_root, MYF(0)); /* the table is allocated in its own root */
|
||||
thd->proc_info=save_proc_info;
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
@ -9063,7 +8865,7 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param,
|
||||
end_select function to use. This function can't fail.
|
||||
*/
|
||||
|
||||
static Next_select_func setup_end_select_func(JOIN *join)
|
||||
Next_select_func setup_end_select_func(JOIN *join)
|
||||
{
|
||||
TABLE *table= join->tmp_table;
|
||||
Next_select_func end_select;
|
||||
@ -9218,7 +9020,7 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
|
||||
}
|
||||
|
||||
|
||||
static enum_nested_loop_state
|
||||
enum_nested_loop_state
|
||||
sub_select_cache(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
|
||||
{
|
||||
enum_nested_loop_state rc;
|
||||
@ -9359,7 +9161,7 @@ sub_select_cache(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
|
||||
return one of enum_nested_loop_state, except NESTED_LOOP_NO_MORE_ROWS.
|
||||
*/
|
||||
|
||||
static enum_nested_loop_state
|
||||
enum_nested_loop_state
|
||||
sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
|
||||
{
|
||||
join_tab->table->null_row=0;
|
||||
@ -12378,6 +12180,11 @@ calc_group_buffer(JOIN *join,ORDER *group)
|
||||
key_length+=MAX_BLOB_WIDTH; // Can't be used as a key
|
||||
else if (field->type() == MYSQL_TYPE_VARCHAR)
|
||||
key_length+= field->field_length + HA_KEY_BLOB_LENGTH;
|
||||
else if (field->type() == FIELD_TYPE_BIT)
|
||||
{
|
||||
/* Bit is usually stored as a longlong key for group fields */
|
||||
key_length+= 8; // Big enough
|
||||
}
|
||||
else
|
||||
key_length+= field->pack_length();
|
||||
}
|
||||
@ -13782,8 +13589,7 @@ bool mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
|
||||
unit->fake_select_lex->select_number= UINT_MAX; // jost for initialization
|
||||
unit->fake_select_lex->type= "UNION RESULT";
|
||||
unit->fake_select_lex->options|= SELECT_DESCRIBE;
|
||||
if (!(res= unit->prepare(thd, result, SELECT_NO_UNLOCK | SELECT_DESCRIBE,
|
||||
"")))
|
||||
if (!(res= unit->prepare(thd, result, SELECT_NO_UNLOCK | SELECT_DESCRIBE)))
|
||||
res= unit->exec();
|
||||
res|= unit->cleanup();
|
||||
}
|
||||
|
Reference in New Issue
Block a user