mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Merge
BitKeeper/etc/logging_ok: auto-union BUILD/autorun.sh: Auto merged BitKeeper/etc/config: Auto merged Makefile.am: Auto merged include/my_bitmap.h: Auto merged libmysqld/Makefile.am: Auto merged mysql-test/mysql-test-run.pl: Auto merged mysql-test/mysql-test-run.sh: Auto merged mysql-test/r/grant.result: Auto merged mysql-test/r/ps_6bdb.result: Auto merged mysql-test/r/ps_7ndb.result: Auto merged mysys/Makefile.am: Auto merged mysys/default.c: Auto merged scripts/mysql_create_system_tables.sh: Auto merged scripts/mysql_fix_privilege_tables.sql: Auto merged sql/Makefile.am: Auto merged sql/field.cc: Auto merged sql/field.h: Auto merged sql/ha_ndbcluster.h: Auto merged sql/handler.cc: Auto merged sql/handler.h: Auto merged sql/item.cc: Auto merged sql/log_event.cc: Auto merged sql/mysql_priv.h: Auto merged sql/opt_range.cc: Auto merged sql/sql_acl.cc: Auto merged sql/sql_acl.h: Auto merged sql/sql_base.cc: Auto merged sql/sql_cache.cc: Auto merged sql/sql_class.h: Auto merged sql/sql_delete.cc: Auto merged sql/sql_lex.cc: Auto merged sql/sql_parse.cc: Auto merged sql/sql_table.cc: Auto merged sql/sql_udf.cc: Auto merged sql/sql_yacc.yy: Auto merged storage/heap/Makefile.am: Auto merged storage/heap/hp_hash.c: Auto merged storage/innobase/btr/btr0btr.c: Auto merged storage/innobase/btr/btr0cur.c: Auto merged storage/innobase/configure.in: Auto merged storage/innobase/fil/fil0fil.c: Auto merged storage/innobase/ibuf/ibuf0ibuf.c: Auto merged storage/innobase/include/os0file.h: Auto merged storage/innobase/include/page0cur.h: Auto merged storage/innobase/include/row0mysql.h: Auto merged storage/innobase/include/srv0srv.h: Auto merged storage/innobase/include/trx0trx.h: Auto merged storage/innobase/include/trx0trx.ic: Auto merged storage/innobase/lock/lock0lock.c: Auto merged storage/innobase/log/log0recv.c: Auto merged storage/innobase/os/os0file.c: Auto merged storage/innobase/page/page0cur.c: Auto merged storage/innobase/page/page0page.c: Auto merged storage/innobase/rem/rem0rec.c: Auto merged storage/innobase/row/row0mysql.c: Auto merged storage/innobase/row/row0sel.c: Auto merged storage/innobase/row/row0upd.c: Auto merged storage/innobase/srv/srv0srv.c: Auto merged storage/innobase/trx/trx0trx.c: Auto merged storage/innobase/trx/trx0undo.c: Auto merged storage/myisam/Makefile.am: Auto merged storage/myisam/mi_create.c: Auto merged storage/myisam/mi_open.c: Auto merged storage/myisam/mi_packrec.c: Auto merged storage/myisam/mi_unique.c: Auto merged storage/myisam/myisampack.c: Auto merged storage/myisammrg/Makefile.am: Auto merged storage/ndb/include/mgmcommon/ConfigRetriever.hpp: Auto merged storage/ndb/include/transporter/TransporterDefinitions.hpp: Auto merged storage/ndb/src/common/mgmcommon/ConfigRetriever.cpp: Auto merged storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp: Auto merged storage/ndb/src/mgmsrv/main.cpp: Auto merged storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp: Auto merged storage/ndb/test/ndbapi/create_tab.cpp: Auto merged storage/ndb/test/ndbapi/testBlobs.cpp: Auto merged strings/ctype-big5.c: Auto merged strings/ctype-ucs2.c: Auto merged support-files/mysql.spec.sh: Auto merged configure.in: merge mysql-test/t/disabled.def: merge mysys/my_bitmap.c: SCCS merged sql/ha_federated.cc: merge sql/ha_innodb.cc: merge sql/ha_ndbcluster.cc: merge sql/mysqld.cc: e merge sql/sql_insert.cc: merge sql/sql_lex.h: merge sql/sql_load.cc: merge sql/sql_select.cc: merge e C sql/sql_update.cc: merge sql/table.cc: merge
This commit is contained in:
@ -28,8 +28,6 @@
|
||||
#include <hash.h>
|
||||
#include <ft_global.h>
|
||||
|
||||
typedef uint32 cache_rec_length_type;
|
||||
|
||||
const char *join_type_str[]={ "UNKNOWN","system","const","eq_ref","ref",
|
||||
"MAYBE_REF","ALL","range","index","fulltext",
|
||||
"ref_or_null","unique_subquery","index_subquery",
|
||||
@ -87,10 +85,9 @@ static void update_depend_map(JOIN *join, ORDER *order);
|
||||
static ORDER *remove_const(JOIN *join,ORDER *first_order,COND *cond,
|
||||
bool change_list, bool *simple_order);
|
||||
static int return_zero_rows(JOIN *join, select_result *res,TABLE_LIST *tables,
|
||||
List<Item> &fields, bool send_row,
|
||||
uint select_options, const char *info,
|
||||
Item *having, Procedure *proc,
|
||||
SELECT_LEX_UNIT *unit);
|
||||
List<Item> &fields, bool send_row,
|
||||
uint select_options, const char *info,
|
||||
Item *having);
|
||||
static COND *build_equal_items(THD *thd, COND *cond,
|
||||
COND_EQUAL *inherited,
|
||||
List<TABLE_LIST> *join_list,
|
||||
@ -183,10 +180,10 @@ static void reset_cache_read(JOIN_CACHE *cache);
|
||||
static void reset_cache_write(JOIN_CACHE *cache);
|
||||
static void read_cached_record(JOIN_TAB *tab);
|
||||
static bool cmp_buffer_with_ref(JOIN_TAB *tab);
|
||||
static bool setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields,
|
||||
List<Item> &all_fields,ORDER *new_order);
|
||||
static ORDER *create_distinct_group(THD *thd, ORDER *order,
|
||||
List<Item> &fields,
|
||||
static bool setup_new_fields(THD *thd, List<Item> &fields,
|
||||
List<Item> &all_fields, ORDER *new_order);
|
||||
static ORDER *create_distinct_group(THD *thd, Item **ref_pointer_array,
|
||||
ORDER *order, List<Item> &fields,
|
||||
bool *all_order_by_fields_used);
|
||||
static bool test_if_subpart(ORDER *a,ORDER *b);
|
||||
static TABLE *get_sort_by_table(ORDER *a,ORDER *b,TABLE_LIST *tables);
|
||||
@ -284,6 +281,7 @@ inline int setup_without_group(THD *thd, Item **ref_pointer_array,
|
||||
save_allow_sum_func= thd->allow_sum_func;
|
||||
thd->allow_sum_func= 0;
|
||||
res= setup_conds(thd, tables, leaves, conds);
|
||||
|
||||
thd->allow_sum_func= save_allow_sum_func;
|
||||
res= res || setup_order(thd, ref_pointer_array, tables, fields, all_fields,
|
||||
order);
|
||||
@ -340,11 +338,12 @@ JOIN::prepare(Item ***rref_pointer_array,
|
||||
/* Check that all tables, fields, conds and order are ok */
|
||||
|
||||
if ((!(select_options & OPTION_SETUP_TABLES_DONE) &&
|
||||
setup_tables(thd, tables_list, &conds, &select_lex->leaf_tables,
|
||||
setup_tables(thd, &select_lex->context,
|
||||
tables_list, &conds, &select_lex->leaf_tables,
|
||||
FALSE)) ||
|
||||
setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) ||
|
||||
select_lex->setup_ref_array(thd, og_num) ||
|
||||
setup_fields(thd, (*rref_pointer_array), tables_list, fields_list, 1,
|
||||
setup_fields(thd, (*rref_pointer_array), fields_list, 1,
|
||||
&all_fields, 1) ||
|
||||
setup_without_group(thd, (*rref_pointer_array), tables_list,
|
||||
select_lex->leaf_tables, fields_list,
|
||||
@ -360,7 +359,7 @@ JOIN::prepare(Item ***rref_pointer_array,
|
||||
thd->allow_sum_func=1;
|
||||
select_lex->having_fix_field= 1;
|
||||
bool having_fix_rc= (!having->fixed &&
|
||||
(having->fix_fields(thd, tables_list, &having) ||
|
||||
(having->fix_fields(thd, &having) ||
|
||||
having->check_cols(1)));
|
||||
select_lex->having_fix_field= 0;
|
||||
if (having_fix_rc || thd->net.report_error)
|
||||
@ -433,7 +432,7 @@ JOIN::prepare(Item ***rref_pointer_array,
|
||||
goto err; /* purecov: inspected */
|
||||
if (procedure)
|
||||
{
|
||||
if (setup_new_fields(thd, tables_list, fields_list, all_fields,
|
||||
if (setup_new_fields(thd, fields_list, all_fields,
|
||||
procedure->param_fields))
|
||||
goto err; /* purecov: inspected */
|
||||
if (procedure->group)
|
||||
@ -567,7 +566,7 @@ JOIN::optimize()
|
||||
Item_cond_and can't be fixed after creation, so we do not check
|
||||
conds->fixed
|
||||
*/
|
||||
conds->fix_fields(thd, tables_list, &conds);
|
||||
conds->fix_fields(thd, &conds);
|
||||
conds->change_ref_to_fields(thd, tables_list);
|
||||
conds->top_level_item();
|
||||
having= 0;
|
||||
@ -780,7 +779,8 @@ JOIN::optimize()
|
||||
bool all_order_fields_used;
|
||||
if (order)
|
||||
skip_sort_order= test_if_skip_sort_order(tab, order, select_limit, 1);
|
||||
if ((group_list=create_distinct_group(thd, order, fields_list,
|
||||
if ((group_list=create_distinct_group(thd, select_lex->ref_pointer_array,
|
||||
order, fields_list,
|
||||
&all_order_fields_used)))
|
||||
{
|
||||
bool skip_group= (skip_sort_order &&
|
||||
@ -1114,7 +1114,6 @@ int
|
||||
JOIN::reinit()
|
||||
{
|
||||
DBUG_ENTER("JOIN::reinit");
|
||||
|
||||
first_record= 0;
|
||||
|
||||
if (exec_tmp_table1)
|
||||
@ -1223,8 +1222,7 @@ JOIN::exec()
|
||||
send_row_on_empty_set(),
|
||||
select_options,
|
||||
zero_result_cause,
|
||||
having, procedure,
|
||||
unit);
|
||||
having);
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
@ -1433,7 +1431,7 @@ JOIN::exec()
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
end_read_record(&curr_join->join_tab->read_record);
|
||||
curr_join->const_tables= curr_join->tables; // Mark free for join_free()
|
||||
curr_join->const_tables= curr_join->tables; // Mark free for cleanup()
|
||||
curr_join->join_tab[0].table= 0; // Table is freed
|
||||
|
||||
// No sum funcs anymore
|
||||
@ -1663,9 +1661,9 @@ JOIN::exec()
|
||||
*/
|
||||
|
||||
int
|
||||
JOIN::cleanup()
|
||||
JOIN::destroy()
|
||||
{
|
||||
DBUG_ENTER("JOIN::cleanup");
|
||||
DBUG_ENTER("JOIN::destroy");
|
||||
select_lex->join= 0;
|
||||
|
||||
if (tmp_join)
|
||||
@ -1680,12 +1678,11 @@ JOIN::cleanup()
|
||||
}
|
||||
tmp_join->tmp_join= 0;
|
||||
tmp_table_param.copy_field=0;
|
||||
DBUG_RETURN(tmp_join->cleanup());
|
||||
DBUG_RETURN(tmp_join->destroy());
|
||||
}
|
||||
cond_equal= 0;
|
||||
|
||||
lock=0; // It's faster to unlock later
|
||||
join_free(1);
|
||||
cleanup(1);
|
||||
if (exec_tmp_table1)
|
||||
free_tmp_table(thd, exec_tmp_table1);
|
||||
if (exec_tmp_table2)
|
||||
@ -1693,12 +1690,6 @@ JOIN::cleanup()
|
||||
delete select;
|
||||
delete_dynamic(&keyuse);
|
||||
delete procedure;
|
||||
for (SELECT_LEX_UNIT *lex_unit= select_lex->first_inner_unit();
|
||||
lex_unit != 0;
|
||||
lex_unit= lex_unit->next_unit())
|
||||
{
|
||||
error|= lex_unit->cleanup();
|
||||
}
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
@ -1742,6 +1733,7 @@ Cursor::init_from_thd(THD *thd)
|
||||
lock= thd->lock;
|
||||
query_id= thd->query_id;
|
||||
free_list= thd->free_list;
|
||||
change_list= thd->change_list;
|
||||
reset_thd(thd);
|
||||
/*
|
||||
XXX: thd->locked_tables is not changed.
|
||||
@ -1758,6 +1750,7 @@ Cursor::reset_thd(THD *thd)
|
||||
thd->open_tables= 0;
|
||||
thd->lock= 0;
|
||||
thd->free_list= 0;
|
||||
thd->change_list.empty();
|
||||
}
|
||||
|
||||
|
||||
@ -1831,6 +1824,7 @@ Cursor::fetch(ulong num_rows)
|
||||
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_item_arena(this, &backup_arena);
|
||||
|
||||
@ -1847,10 +1841,8 @@ Cursor::fetch(ulong num_rows)
|
||||
#ifdef USING_TRANSACTIONS
|
||||
ha_release_temporary_latches(thd);
|
||||
#endif
|
||||
|
||||
/* Grab free_list here to correctly free it in close */
|
||||
thd->restore_backup_item_arena(this, &backup_arena);
|
||||
DBUG_ASSERT(thd->free_list == 0);
|
||||
reset_thd(thd);
|
||||
|
||||
if (error == NESTED_LOOP_CURSOR_LIMIT)
|
||||
{
|
||||
@ -1858,10 +1850,12 @@ Cursor::fetch(ulong num_rows)
|
||||
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();
|
||||
close(TRUE);
|
||||
if (error == NESTED_LOOP_OK)
|
||||
{
|
||||
thd->server_status|= SERVER_STATUS_LAST_ROW_SENT;
|
||||
@ -1876,22 +1870,23 @@ Cursor::fetch(ulong num_rows)
|
||||
|
||||
|
||||
void
|
||||
Cursor::close()
|
||||
Cursor::close(bool is_active)
|
||||
{
|
||||
THD *thd= join->thd;
|
||||
DBUG_ENTER("Cursor::close");
|
||||
|
||||
join->join_free(0);
|
||||
/*
|
||||
In case of UNIONs JOIN is freed inside of unit->cleanup(),
|
||||
otherwise in select_lex->cleanup().
|
||||
*/
|
||||
if (unit)
|
||||
{
|
||||
/* In case of UNIONs JOIN is freed inside unit->cleanup() */
|
||||
unit->cleanup();
|
||||
}
|
||||
(void) unit->cleanup();
|
||||
else
|
||||
(void) join->select_lex->cleanup();
|
||||
|
||||
if (is_active)
|
||||
close_thread_tables(thd);
|
||||
else
|
||||
{
|
||||
join->cleanup();
|
||||
delete join;
|
||||
}
|
||||
{
|
||||
/* XXX: Another hack: closing tables used in the cursor */
|
||||
DBUG_ASSERT(lock || open_tables || derived_tables);
|
||||
@ -1910,13 +1905,8 @@ Cursor::close()
|
||||
}
|
||||
join= 0;
|
||||
unit= 0;
|
||||
free_items(free_list);
|
||||
free_list= 0;
|
||||
/*
|
||||
Must be last, as some memory might be allocated for free purposes,
|
||||
like in free_tmp_table() (TODO: fix this issue)
|
||||
*/
|
||||
free_root(mem_root, MYF(0));
|
||||
free_items();
|
||||
change_list.empty();
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
@ -1924,7 +1914,7 @@ Cursor::close()
|
||||
Cursor::~Cursor()
|
||||
{
|
||||
if (is_open())
|
||||
close();
|
||||
close(FALSE);
|
||||
}
|
||||
|
||||
/*********************************************************************/
|
||||
@ -1986,6 +1976,7 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
|
||||
bool free_join= 1;
|
||||
DBUG_ENTER("mysql_select");
|
||||
|
||||
select_lex->context.resolve_in_select_list= TRUE;
|
||||
JOIN *join;
|
||||
if (select_lex->join != 0)
|
||||
{
|
||||
@ -2068,8 +2059,7 @@ err:
|
||||
if (free_join)
|
||||
{
|
||||
thd->proc_info="end";
|
||||
err= join->cleanup();
|
||||
delete join;
|
||||
err= select_lex->cleanup();
|
||||
DBUG_RETURN(err || thd->net.report_error);
|
||||
}
|
||||
DBUG_RETURN(join->error);
|
||||
@ -5902,29 +5892,68 @@ void JOIN_TAB::cleanup()
|
||||
}
|
||||
|
||||
|
||||
void JOIN::join_free(bool full)
|
||||
{
|
||||
SELECT_LEX_UNIT *unit;
|
||||
SELECT_LEX *sl;
|
||||
DBUG_ENTER("JOIN::join_free");
|
||||
|
||||
/*
|
||||
Optimization: if not EXPLAIN and we are done with the JOIN,
|
||||
free all tables.
|
||||
*/
|
||||
full= full || (!select_lex->uncacheable && !thd->lex->describe);
|
||||
|
||||
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())
|
||||
{
|
||||
JOIN *join= sl->join;
|
||||
if (join)
|
||||
join->join_free(full);
|
||||
}
|
||||
|
||||
/*
|
||||
We are not using tables anymore
|
||||
Unlock all tables. We may be in an INSERT .... SELECT statement.
|
||||
*/
|
||||
if (full && lock && thd->lock && !(select_options & SELECT_NO_UNLOCK) &&
|
||||
!select_lex->subquery_in_having &&
|
||||
(select_lex == (thd->lex->unit.fake_select_lex ?
|
||||
thd->lex->unit.fake_select_lex : &thd->lex->select_lex)))
|
||||
{
|
||||
/*
|
||||
TODO: unlock tables even if the join isn't top level select in the
|
||||
tree.
|
||||
*/
|
||||
mysql_unlock_read_tables(thd, lock); // Don't free join->lock
|
||||
lock= 0;
|
||||
}
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Free resources of given join
|
||||
|
||||
SYNOPSIS
|
||||
JOIN::join_free()
|
||||
JOIN::cleanup()
|
||||
fill - true if we should free all resources, call with full==1 should be
|
||||
last, before it this function can be called with full==0
|
||||
|
||||
NOTE: with subquery this function definitely will be called several times,
|
||||
but even for simple query it can be called several times.
|
||||
*/
|
||||
void
|
||||
JOIN::join_free(bool full)
|
||||
{
|
||||
JOIN_TAB *tab,*end;
|
||||
DBUG_ENTER("JOIN::join_free");
|
||||
|
||||
full= full || (!select_lex->uncacheable &&
|
||||
!thd->lex->subqueries &&
|
||||
!thd->lex->describe); // do not cleanup too early on EXPLAIN
|
||||
void JOIN::cleanup(bool full)
|
||||
{
|
||||
DBUG_ENTER("JOIN::cleanup");
|
||||
|
||||
if (table)
|
||||
{
|
||||
JOIN_TAB *tab,*end;
|
||||
/*
|
||||
Only a sorted table may be cached. This sorted table is always the
|
||||
first non const table in join->table
|
||||
@ -5935,16 +5964,6 @@ JOIN::join_free(bool full)
|
||||
filesort_free_buffers(table[const_tables]);
|
||||
}
|
||||
|
||||
for (SELECT_LEX_UNIT *unit= select_lex->first_inner_unit(); unit;
|
||||
unit= unit->next_unit())
|
||||
{
|
||||
JOIN *join;
|
||||
for (SELECT_LEX *sl= unit->first_select_in_union(); sl;
|
||||
sl= sl->next_select())
|
||||
if ((join= sl->join))
|
||||
join->join_free(full);
|
||||
}
|
||||
|
||||
if (full)
|
||||
{
|
||||
for (tab= join_tab, end= tab+tables; tab != end; tab++)
|
||||
@ -5961,25 +5980,14 @@ JOIN::join_free(bool full)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
We are not using tables anymore
|
||||
Unlock all tables. We may be in an INSERT .... SELECT statement.
|
||||
*/
|
||||
if (full && lock && thd->lock && !(select_options & SELECT_NO_UNLOCK) &&
|
||||
!select_lex->subquery_in_having)
|
||||
{
|
||||
// TODO: unlock tables even if the join isn't top level select in the tree
|
||||
if (select_lex == (thd->lex->unit.fake_select_lex ?
|
||||
thd->lex->unit.fake_select_lex : &thd->lex->select_lex))
|
||||
{
|
||||
mysql_unlock_read_tables(thd, lock); // Don't free join->lock
|
||||
lock=0;
|
||||
}
|
||||
}
|
||||
|
||||
if (full)
|
||||
{
|
||||
if (tmp_join)
|
||||
tmp_table_param.copy_field= 0;
|
||||
group_fields.delete_elements();
|
||||
/*
|
||||
We can't call delete_elements() on copy_funcs as this will cause
|
||||
@ -6214,8 +6222,7 @@ remove_const(JOIN *join,ORDER *first_order, COND *cond,
|
||||
static int
|
||||
return_zero_rows(JOIN *join, select_result *result,TABLE_LIST *tables,
|
||||
List<Item> &fields, bool send_row, uint select_options,
|
||||
const char *info, Item *having, Procedure *procedure,
|
||||
SELECT_LEX_UNIT *unit)
|
||||
const char *info, Item *having)
|
||||
{
|
||||
DBUG_ENTER("return_zero_rows");
|
||||
|
||||
@ -7438,7 +7445,7 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top)
|
||||
conds->top_level_item();
|
||||
/* conds is always a new item as both cond and on_expr existed */
|
||||
DBUG_ASSERT(!conds->fixed);
|
||||
conds->fix_fields(join->thd, 0, &conds);
|
||||
conds->fix_fields(join->thd, &conds);
|
||||
}
|
||||
else
|
||||
conds= table->on_expr;
|
||||
@ -7659,7 +7666,7 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value)
|
||||
cond->fixed, also it do not need tables so we use 0 as second
|
||||
argument.
|
||||
*/
|
||||
cond->fix_fields(thd, 0, &cond);
|
||||
cond->fix_fields(thd, &cond);
|
||||
}
|
||||
thd->insert_id(0); // Clear for next request
|
||||
}
|
||||
@ -7678,7 +7685,7 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value)
|
||||
cond->fixed, also it do not need tables so we use 0 as second
|
||||
argument.
|
||||
*/
|
||||
cond->fix_fields(thd, 0, &cond);
|
||||
cond->fix_fields(thd, &cond);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -7950,7 +7957,9 @@ Field *create_tmp_field_for_schema(THD *thd, Item *item, TABLE *table)
|
||||
|
||||
Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
|
||||
Item ***copy_func, Field **from_field,
|
||||
bool group, bool modify_item, uint convert_blob_length)
|
||||
bool group, bool modify_item,
|
||||
bool table_cant_handle_bit_fields,
|
||||
uint convert_blob_length)
|
||||
{
|
||||
switch (type) {
|
||||
case Item::SUM_FUNC_ITEM:
|
||||
@ -7965,15 +7974,20 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
|
||||
case Item::DEFAULT_VALUE_ITEM:
|
||||
{
|
||||
Item_field *field= (Item_field*) item;
|
||||
if (table_cant_handle_bit_fields && field->field->type() == FIELD_TYPE_BIT)
|
||||
return create_tmp_field_from_item(thd, item, table, copy_func,
|
||||
modify_item, convert_blob_length);
|
||||
return create_tmp_field_from_field(thd, (*from_field= field->field),
|
||||
item->name, table,
|
||||
modify_item ? (Item_field*) item : NULL,
|
||||
convert_blob_length);
|
||||
}
|
||||
case Item::REF_ITEM:
|
||||
if ( item->real_item()->type() == Item::FIELD_ITEM)
|
||||
{
|
||||
Item *tmp_item;
|
||||
if ((tmp_item= item->real_item())->type() == Item::FIELD_ITEM)
|
||||
{
|
||||
Item_field *field= (Item_field*) *((Item_ref*)item)->ref;
|
||||
Item_field *field= (Item_field*) tmp_item;
|
||||
Field *new_field= create_tmp_field_from_field(thd,
|
||||
(*from_field= field->field),
|
||||
item->name, table,
|
||||
@ -7983,6 +7997,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
|
||||
item->set_result_field(new_field);
|
||||
return new_field;
|
||||
}
|
||||
}
|
||||
case Item::FUNC_ITEM:
|
||||
case Item::COND_ITEM:
|
||||
case Item::FIELD_AVG_ITEM:
|
||||
@ -8186,6 +8201,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,
|
||||
param->convert_blob_length);
|
||||
if (!new_field)
|
||||
goto err; // Should be OOM
|
||||
@ -8196,6 +8212,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
|
||||
*blob_field++= (uint) (reg_field - table->field);
|
||||
blob_count++;
|
||||
}
|
||||
new_field->field_index= (uint) (reg_field - table->field);
|
||||
*(reg_field++)= new_field;
|
||||
if (new_field->real_type() == MYSQL_TYPE_STRING ||
|
||||
new_field->real_type() == MYSQL_TYPE_VARCHAR)
|
||||
@ -8234,7 +8251,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
|
||||
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,
|
||||
not_all_columns || group != 0, 0,
|
||||
param->convert_blob_length);
|
||||
|
||||
if (!new_field)
|
||||
@ -8263,6 +8280,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
|
||||
}
|
||||
new_field->query_id= thd->query_id;
|
||||
new_field->fieldnr= ++fieldnr;
|
||||
new_field->field_index= (uint) (reg_field - table->field);
|
||||
*(reg_field++) =new_field;
|
||||
}
|
||||
if (!--hidden_field_count)
|
||||
@ -8377,6 +8395,13 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
|
||||
}
|
||||
else
|
||||
field->move_field((char*) pos,(uchar*) 0,0);
|
||||
if (field->type() == FIELD_TYPE_BIT)
|
||||
{
|
||||
/* We have to reserve place for extra bits among null bits */
|
||||
((Field_bit*) field)->set_bit_ptr(null_flags + null_count / 8,
|
||||
null_count & 7);
|
||||
null_count+= (field->field_length & 7);
|
||||
}
|
||||
field->reset();
|
||||
if (from_field[i])
|
||||
{ /* Not a table Item */
|
||||
@ -11168,8 +11193,7 @@ static bool fix_having(JOIN *join, Item **having)
|
||||
else // This should never happen
|
||||
if (!(table->select->cond= new Item_cond_and(table->select->cond,
|
||||
sort_table_cond)) ||
|
||||
table->select->cond->fix_fields(join->thd, join->tables_list,
|
||||
&table->select->cond))
|
||||
table->select->cond->fix_fields(join->thd, &table->select->cond))
|
||||
return 1;
|
||||
table->select_cond=table->select->cond;
|
||||
table->select_cond->top_level_item();
|
||||
@ -11619,7 +11643,7 @@ used_blob_length(CACHE_FIELD **ptr)
|
||||
static bool
|
||||
store_record_in_cache(JOIN_CACHE *cache)
|
||||
{
|
||||
cache_rec_length_type length;
|
||||
uint length;
|
||||
uchar *pos;
|
||||
CACHE_FIELD *copy,*end_field;
|
||||
bool last_record;
|
||||
@ -11664,9 +11688,9 @@ store_record_in_cache(JOIN_CACHE *cache)
|
||||
end > str && end[-1] == ' ' ;
|
||||
end--) ;
|
||||
length=(uint) (end-str);
|
||||
memcpy(pos+sizeof(length), str, length);
|
||||
memcpy_fixed(pos, &length, sizeof(length));
|
||||
pos+= length+sizeof(length);
|
||||
memcpy(pos+2, str, length);
|
||||
int2store(pos, length);
|
||||
pos+= length+2;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -11700,7 +11724,7 @@ static void
|
||||
read_cached_record(JOIN_TAB *tab)
|
||||
{
|
||||
uchar *pos;
|
||||
cache_rec_length_type length;
|
||||
uint length;
|
||||
bool last_record;
|
||||
CACHE_FIELD *copy,*end_field;
|
||||
|
||||
@ -11729,10 +11753,10 @@ read_cached_record(JOIN_TAB *tab)
|
||||
{
|
||||
if (copy->strip)
|
||||
{
|
||||
memcpy_fixed(&length, pos, sizeof(length));
|
||||
memcpy(copy->str, pos+sizeof(length), length);
|
||||
length= uint2korr(pos);
|
||||
memcpy(copy->str, pos+2, length);
|
||||
memset(copy->str+length, ' ', copy->length-length);
|
||||
pos+= sizeof(length)+length;
|
||||
pos+= 2 + length;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -11769,10 +11793,10 @@ cp_buffer_from_ref(THD *thd, TABLE_REF *ref)
|
||||
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
|
||||
for (store_key **copy=ref->key_copy ; *copy ; copy++)
|
||||
{
|
||||
if ((*copy)->copy())
|
||||
if ((*copy)->copy() & 1)
|
||||
{
|
||||
thd->count_cuted_fields= save_count_cuted_fields;
|
||||
return 1; // Something went wrong
|
||||
return 1; // Something went wrong
|
||||
}
|
||||
}
|
||||
thd->count_cuted_fields= save_count_cuted_fields;
|
||||
@ -11789,14 +11813,13 @@ cp_buffer_from_ref(THD *thd, TABLE_REF *ref)
|
||||
|
||||
SYNOPSIS
|
||||
find_order_in_list()
|
||||
thd [in] Pointer to current thread structure
|
||||
ref_pointer_array [in/out] All select, group and order by fields
|
||||
tables [in] List of tables to search in (usually FROM clause)
|
||||
order [in] Column reference to be resolved
|
||||
fields [in] List of fields to search in (usually SELECT list)
|
||||
all_fields [in/out] All select, group and order by fields
|
||||
is_group_field [in] True if order is a GROUP field, false if
|
||||
ORDER by field
|
||||
thd Pointer to current thread structure
|
||||
ref_pointer_array All select, group and order by fields
|
||||
tables List of tables to search in (usually FROM clause)
|
||||
order Column reference to be resolved
|
||||
fields List of fields to search in (usually SELECT list)
|
||||
all_fields All select, group and order by fields
|
||||
is_group_field True if order is a GROUP field, false if ORDER by field
|
||||
|
||||
DESCRIPTION
|
||||
Given a column reference (represented by 'order') from a GROUP BY or ORDER
|
||||
@ -11813,6 +11836,8 @@ cp_buffer_from_ref(THD *thd, TABLE_REF *ref)
|
||||
RETURN
|
||||
FALSE if OK
|
||||
TRUE if error occurred
|
||||
|
||||
ref_pointer_array and all_fields are updated
|
||||
*/
|
||||
|
||||
static bool
|
||||
@ -11858,26 +11883,25 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
|
||||
original field name, we should additionaly check if we have conflict
|
||||
for this name (in case if we would perform lookup in all tables).
|
||||
*/
|
||||
if (unaliased && !order_item->fixed && order_item->fix_fields(thd, tables,
|
||||
order->item))
|
||||
if (unaliased && !order_item->fixed &&
|
||||
order_item->fix_fields(thd, order->item))
|
||||
return TRUE;
|
||||
|
||||
/* Lookup the current GROUP field in the FROM clause. */
|
||||
order_item_type= order_item->type();
|
||||
from_field= (Field*) not_found_field;
|
||||
if (is_group_field &&
|
||||
order_item_type == Item::FIELD_ITEM ||
|
||||
order_item_type == Item::REF_ITEM)
|
||||
{
|
||||
from_field= find_field_in_tables(thd, (Item_ident*) order_item, tables,
|
||||
&view_ref, IGNORE_ERRORS, TRUE);
|
||||
if(!from_field)
|
||||
from_field= (Field*) not_found_field;
|
||||
&view_ref, IGNORE_ERRORS, TRUE,
|
||||
FALSE);
|
||||
if (!from_field)
|
||||
from_field= (Field*) not_found_field;
|
||||
}
|
||||
else
|
||||
from_field= (Field*) not_found_field;
|
||||
|
||||
if (from_field == not_found_field ||
|
||||
from_field &&
|
||||
(from_field != view_ref_found ?
|
||||
/* it is field of base table => check that fields are same */
|
||||
((*select_item)->type() == Item::FIELD_ITEM &&
|
||||
@ -11890,43 +11914,46 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
|
||||
view_ref->type() == Item::REF_ITEM &&
|
||||
((Item_ref *) (*select_item))->ref ==
|
||||
((Item_ref *) view_ref)->ref)))
|
||||
/*
|
||||
If there is no such field in the FROM clause, or it is the same field as
|
||||
the one found in the SELECT clause, then use the Item created for the
|
||||
SELECT field. As a result if there was a derived field that 'shadowed'
|
||||
a table field with the same name, the table field will be chosen over
|
||||
the derived field.
|
||||
*/
|
||||
{
|
||||
/*
|
||||
If there is no such field in the FROM clause, or it is the same field
|
||||
as the one found in the SELECT clause, then use the Item created for
|
||||
the SELECT field. As a result if there was a derived field that
|
||||
'shadowed' a table field with the same name, the table field will be
|
||||
chosen over the derived field.
|
||||
*/
|
||||
order->item= ref_pointer_array + counter;
|
||||
order->in_field_list=1;
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
There is a field with the same name in the FROM clause. This is the field
|
||||
that will be chosen. In this case we issue a warning so the user knows
|
||||
that the field from the FROM clause overshadows the column reference from
|
||||
the SELECT list.
|
||||
There is a field with the same name in the FROM clause. This
|
||||
is the field that will be chosen. In this case we issue a
|
||||
warning so the user knows that the field from the FROM clause
|
||||
overshadows the column reference from the SELECT list.
|
||||
*/
|
||||
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_NON_UNIQ_ERROR,
|
||||
ER(ER_NON_UNIQ_ERROR), from_field->field_name,
|
||||
current_thd->where);
|
||||
}
|
||||
}
|
||||
|
||||
order->in_field_list=0;
|
||||
/*
|
||||
The call to order_item->fix_fields() means that here we resolve 'order_item'
|
||||
to a column from a table in the list 'tables', or to a column in some outer
|
||||
query. Exactly because of the second case we come to this point even if
|
||||
(select_item == not_found_item), inspite of that fix_fields() calls
|
||||
find_item_in_list() one more time.
|
||||
The call to order_item->fix_fields() means that here we resolve
|
||||
'order_item' to a column from a table in the list 'tables', or to
|
||||
a column in some outer query. Exactly because of the second case
|
||||
we come to this point even if (select_item == not_found_item),
|
||||
inspite of that fix_fields() calls find_item_in_list() one more
|
||||
time.
|
||||
|
||||
We check order_item->fixed because Item_func_group_concat can put
|
||||
arguments for which fix_fields already was called.
|
||||
*/
|
||||
if (!order_item->fixed &&
|
||||
(order_item->fix_fields(thd, tables, order->item) ||
|
||||
(order_item->fix_fields(thd, order->item) ||
|
||||
(order_item= *order->item)->check_cols(1) ||
|
||||
thd->is_fatal_error))
|
||||
return TRUE; /* Wrong field. */
|
||||
@ -12038,7 +12065,7 @@ setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
|
||||
*/
|
||||
|
||||
static bool
|
||||
setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields,
|
||||
setup_new_fields(THD *thd, List<Item> &fields,
|
||||
List<Item> &all_fields, ORDER *new_field)
|
||||
{
|
||||
Item **item;
|
||||
@ -12055,7 +12082,7 @@ setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields,
|
||||
else
|
||||
{
|
||||
thd->where="procedure list";
|
||||
if ((*new_field->item)->fix_fields(thd, tables, new_field->item))
|
||||
if ((*new_field->item)->fix_fields(thd, new_field->item))
|
||||
DBUG_RETURN(1); /* purecov: inspected */
|
||||
all_fields.push_front(*new_field->item);
|
||||
new_field->item=all_fields.head_ref();
|
||||
@ -12071,12 +12098,14 @@ setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields,
|
||||
*/
|
||||
|
||||
static ORDER *
|
||||
create_distinct_group(THD *thd, ORDER *order_list, List<Item> &fields,
|
||||
create_distinct_group(THD *thd, Item **ref_pointer_array,
|
||||
ORDER *order_list, List<Item> &fields,
|
||||
bool *all_order_by_fields_used)
|
||||
{
|
||||
List_iterator<Item> li(fields);
|
||||
Item *item;
|
||||
ORDER *order,*group,**prev;
|
||||
uint index= 0;
|
||||
|
||||
*all_order_by_fields_used= 1;
|
||||
while ((item=li++))
|
||||
@ -12108,11 +12137,17 @@ create_distinct_group(THD *thd, ORDER *order_list, List<Item> &fields,
|
||||
ORDER *ord=(ORDER*) thd->calloc(sizeof(ORDER));
|
||||
if (!ord)
|
||||
return 0;
|
||||
ord->item=li.ref();
|
||||
/*
|
||||
We have here only field_list (not all_field_list), so we can use
|
||||
simple indexing of ref_pointer_array (order in the array and in the
|
||||
list are same)
|
||||
*/
|
||||
ord->item= ref_pointer_array + index;
|
||||
ord->asc=1;
|
||||
*prev=ord;
|
||||
prev= &ord->next;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
*prev=0;
|
||||
return group;
|
||||
@ -12135,7 +12170,7 @@ count_field_types(TMP_TABLE_PARAM *param, List<Item> &fields,
|
||||
param->quick_group=1;
|
||||
while ((field=li++))
|
||||
{
|
||||
Item::Type type=field->type();
|
||||
Item::Type type=field->real_item()->type();
|
||||
if (type == Item::FIELD_ITEM)
|
||||
param->field_count++;
|
||||
else if (type == Item::SUM_FUNC_ITEM)
|
||||
@ -12149,7 +12184,7 @@ count_field_types(TMP_TABLE_PARAM *param, List<Item> &fields,
|
||||
|
||||
for (uint i=0 ; i < sum_item->arg_count ; i++)
|
||||
{
|
||||
if (sum_item->args[0]->type() == Item::FIELD_ITEM)
|
||||
if (sum_item->args[0]->real_item()->type() == Item::FIELD_ITEM)
|
||||
param->field_count++;
|
||||
else
|
||||
param->func_count++;
|
||||
@ -12396,9 +12431,10 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
|
||||
param->copy_funcs.empty();
|
||||
for (i= 0; (pos= li++); i++)
|
||||
{
|
||||
if (pos->type() == Item::FIELD_ITEM)
|
||||
if (pos->real_item()->type() == Item::FIELD_ITEM)
|
||||
{
|
||||
Item_field *item;
|
||||
pos= pos->real_item();
|
||||
if (!(item= new Item_field(thd, ((Item_field*) pos))))
|
||||
goto err;
|
||||
pos= item;
|
||||
@ -12853,7 +12889,7 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab)
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
if (!cond->fixed)
|
||||
cond->fix_fields(thd,(TABLE_LIST *) 0, (Item**)&cond);
|
||||
cond->fix_fields(thd, (Item**)&cond);
|
||||
if (join_tab->select)
|
||||
{
|
||||
error=(int) cond->add(join_tab->select->cond);
|
||||
@ -12895,8 +12931,8 @@ void free_underlaid_joins(THD *thd, SELECT_LEX *select)
|
||||
thd reference to the context
|
||||
expr expression to make replacement
|
||||
group_list list of references to group by items
|
||||
changed out: returns 1 if item contains a replaced field item
|
||||
|
||||
changed out: returns 1 if item contains a replaced field item
|
||||
|
||||
DESCRIPTION
|
||||
The function replaces occurrences of group by fields in expr
|
||||
by ref objects for these fields unless they are under aggregate
|
||||
@ -12925,6 +12961,7 @@ static bool change_group_ref(THD *thd, Item_func *expr, ORDER *group_list,
|
||||
{
|
||||
if (expr->arg_count)
|
||||
{
|
||||
Name_resolution_context *context= &thd->lex->current_select->context;
|
||||
Item **arg,**arg_end;
|
||||
for (arg= expr->arguments(),
|
||||
arg_end= expr->arguments()+expr->arg_count;
|
||||
@ -12938,8 +12975,9 @@ static bool change_group_ref(THD *thd, Item_func *expr, ORDER *group_list,
|
||||
{
|
||||
if (item->eq(*group_tmp->item,0))
|
||||
{
|
||||
Item *new_item;
|
||||
if(!(new_item= new Item_ref(group_tmp->item, 0, item->name)))
|
||||
Item *new_item;
|
||||
if(!(new_item= new Item_ref(context, group_tmp->item, 0,
|
||||
item->name)))
|
||||
return 1; // fatal_error is set
|
||||
thd->change_item_tree(arg, new_item);
|
||||
*changed= TRUE;
|
||||
|
Reference in New Issue
Block a user