summaryrefslogtreecommitdiff
path: root/sql/sql_union.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_union.cc')
-rw-r--r--sql/sql_union.cc125
1 files changed, 66 insertions, 59 deletions
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index e0e8f8d42c5..815e04c0111 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -24,14 +24,19 @@
#include "mysql_priv.h"
#include "sql_select.h"
-int mysql_union(THD *thd, LEX *lex, select_result *result,
- SELECT_LEX_UNIT *unit)
+bool mysql_union(THD *thd, LEX *lex, select_result *result,
+ SELECT_LEX_UNIT *unit)
{
DBUG_ENTER("mysql_union");
- int res= 0;
+ bool res;
if (!(res= unit->prepare(thd, result, SELECT_NO_UNLOCK)))
res= unit->exec();
- res|= unit->cleanup();
+ if (!res && thd->cursor && thd->cursor->is_open())
+ {
+ thd->cursor->set_unit(unit);
+ }
+ else
+ res|= unit->cleanup();
DBUG_RETURN(res);
}
@@ -70,8 +75,8 @@ bool select_union::send_data(List<Item> &values)
unit->offset_limit_cnt--;
return 0;
}
- fill_record(table->field, values, 1);
- if (thd->net.report_error || write_record(table,&info))
+ fill_record(thd, table->field, values, 1);
+ if (thd->net.report_error || write_record(thd, table,&info))
{
if (thd->net.last_errno == ER_RECORD_FILE_FULL)
{
@@ -98,8 +103,7 @@ bool select_union::flush()
int error;
if ((error=table->file->extra(HA_EXTRA_NO_CACHE)))
{
- table->file->print_error(error,MYF(0));
- ::send_error(thd);
+ table->file->print_error(error, MYF(0));
return 1;
}
return 0;
@@ -136,13 +140,13 @@ st_select_lex_unit::init_prepare_fake_select_lex(THD *thd)
fake_select_lex->ftfunc_list= &fake_select_lex->ftfunc_list_alloc;
fake_select_lex->table_list.link_in_list((byte *)&result_table_list,
(byte **)
- &result_table_list.next);
+ &result_table_list.next_local);
return options_tmp;
}
-int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
- ulong additional_options)
+bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
+ ulong additional_options)
{
SELECT_LEX *lex_select_save= thd_arg->lex->current_select;
SELECT_LEX *sl, *first_select;
@@ -171,16 +175,16 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
if (!sl->join->procedure &&
result->prepare(sl->join->fields_list, this))
{
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
}
sl->join->select_options|= SELECT_DESCRIBE;
sl->join->reinit();
}
}
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
prepared= 1;
- res= 0;
+ res= FALSE;
thd_arg->lex->current_select= sl= first_select= first_select_in_union();
found_rows_for_union= first_select->options & OPTION_FOUND_ROWS;
@@ -210,20 +214,17 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
goto err;
thd_arg->lex->current_select= sl;
- offset_limit_cnt= sl->offset_limit;
- select_limit_cnt= sl->select_limit+sl->offset_limit;
- if (select_limit_cnt < sl->select_limit)
- select_limit_cnt= HA_POS_ERROR; // no limit
- if (select_limit_cnt == HA_POS_ERROR || sl->braces)
+ set_limit(sl, sl);
+ if (sl->braces)
sl->options&= ~OPTION_FOUND_ROWS;
can_skip_order_by= is_union &&
(!sl->braces || select_limit_cnt == HA_POS_ERROR);
-
+
res= join->prepare(&sl->ref_pointer_array,
(TABLE_LIST*) sl->table_list.first, sl->with_wild,
sl->where,
- (can_skip_order_by ? 0 : sl->order_list.elements) +
+ (can_skip_order_by ? 0 : sl->order_list.elements) +
sl->group_list.elements,
can_skip_order_by ?
(ORDER*) 0 : (ORDER *)sl->order_list.first,
@@ -235,7 +236,8 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
/* There are no * in the statement anymore (for PS) */
sl->with_wild= 0;
last_procedure= join->procedure;
- if (res || thd_arg->is_fatal_error)
+
+ if ((res= (res || thd_arg->is_fatal_error)))
goto err;
if (sl == first_select)
{
@@ -265,7 +267,7 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
while ((type= tp++, item_tmp= it++))
{
if (((Item_type_holder*)type)->join_types(thd_arg, item_tmp))
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
}
}
@@ -279,6 +281,7 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
List_iterator_fast<Item> tp(types);
Item_arena *arena= thd->current_arena;
Item *type;
+
while ((type= tp++))
{
if (type->result_type() == STRING_RESULT &&
@@ -309,14 +312,10 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
thd_arg->lex->current_select= lex_select_save;
if (!item_list.elements)
{
- /*
- We're in statement prepare or in execution
- of a conventional statement.
- */
+ Field **field;
Item_arena *tmp_arena,backup;
tmp_arena= thd->change_arena_if_needed(&backup);
- Field **field;
for (field= table->field; *field; field++)
{
Item_field *item= new Item_field(*field);
@@ -324,7 +323,7 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
{
if (tmp_arena)
thd->restore_backup_item_arena(tmp_arena, &backup);
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
}
if (tmp_arena)
@@ -333,11 +332,16 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
{
/* prepare fake select to initialize it correctly */
ulong options_tmp= init_prepare_fake_select_lex(thd);
+ /*
+ it should be done only once (because item_list builds only onece
+ per statement)
+ */
+ DBUG_ASSERT(fake_select_lex->join == 0);
if (!(fake_select_lex->join= new JOIN(thd, item_list, thd->options,
result)))
{
fake_select_lex->table_list.empty();
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
fake_select_lex->item_list= item_list;
@@ -354,11 +358,11 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
fake_select_lex->table_list.empty();
}
}
- else if (arena->is_stmt_execute())
+ else if (!arena->is_conventional())
{
/*
- We're in execution of a prepared statement: reset field items
- to point at fields from the created temporary table.
+ We're in execution of a prepared statement or stored procedure:
+ reset field items to point at fields from the created temporary table.
*/
List_iterator_fast<Item> it(item_list);
for (Field **field= table->field; *field; field++)
@@ -372,15 +376,15 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
thd_arg->lex->current_select= lex_select_save;
- DBUG_RETURN(res || thd_arg->is_fatal_error ? 1 : 0);
+ DBUG_RETURN(res || thd_arg->is_fatal_error);
err:
thd_arg->lex->current_select= lex_select_save;
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
-int st_select_lex_unit::exec()
+bool st_select_lex_unit::exec()
{
SELECT_LEX *lex_select_save= thd->lex->current_select;
SELECT_LEX *select_cursor=first_select_in_union();
@@ -389,7 +393,7 @@ int st_select_lex_unit::exec()
DBUG_ENTER("st_select_lex_unit::exec");
if (executed && !uncacheable && !describe)
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
executed= 1;
if (uncacheable || !item || !item->assigned() || describe)
@@ -404,7 +408,7 @@ int st_select_lex_unit::exec()
}
/* re-enabling indexes for next subselect iteration */
if (union_distinct && table->file->enable_indexes(HA_KEY_SWITCH_ALL))
- DBUG_ASSERT(1);
+ DBUG_ASSERT(TRUE);
}
for (SELECT_LEX *sl= select_cursor; sl; sl= sl->next_select())
{
@@ -459,7 +463,7 @@ int st_select_lex_unit::exec()
if (sl == union_distinct)
{
if (table->file->disable_indexes(HA_KEY_SWITCH_ALL))
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
table->no_keyread=1;
}
res= sl->join->error;
@@ -468,7 +472,7 @@ int st_select_lex_unit::exec()
{
examined_rows+= thd->examined_row_count;
thd->lex->current_select= lex_select_save;
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
}
}
if (res)
@@ -494,7 +498,7 @@ int st_select_lex_unit::exec()
optimized= 1;
/* Send result to 'result' */
- res= -1;
+ res= TRUE;
{
List<Item_func_match> empty_list;
empty_list.empty();
@@ -509,11 +513,11 @@ int st_select_lex_unit::exec()
allocate JOIN for fake select only once (prevent
mysql_select automatic allocation)
*/
- if (!(fake_select_lex->join= new JOIN(thd, item_list, thd->options,
- result)))
+ if (!(fake_select_lex->join= new JOIN(thd, item_list,
+ fake_select_lex->options, result)))
{
fake_select_lex->table_list.empty();
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
/*
@@ -525,12 +529,14 @@ int st_select_lex_unit::exec()
else
{
JOIN_TAB *tab,*end;
- for (tab=join->join_tab,end=tab+join->tables ; tab != end ; tab++)
+ for (tab=join->join_tab, end=tab+join->tables ;
+ tab && tab != end ;
+ tab++)
{
delete tab->select;
delete tab->quick;
}
- join->init(thd, item_list, thd->options, result);
+ join->init(thd, item_list, fake_select_lex->options, result);
}
res= mysql_select(thd, &fake_select_lex->ref_pointer_array,
&result_table_list,
@@ -538,7 +544,7 @@ int st_select_lex_unit::exec()
global_parameters->order_list.elements,
(ORDER*)global_parameters->order_list.first,
(ORDER*) NULL, NULL, (ORDER*) NULL,
- options_tmp | SELECT_NO_UNLOCK,
+ fake_select_lex->options | SELECT_NO_UNLOCK,
result, this, fake_select_lex);
fake_select_lex->table_list.empty();
@@ -558,14 +564,15 @@ int st_select_lex_unit::exec()
}
-int st_select_lex_unit::cleanup()
+bool st_select_lex_unit::cleanup()
{
int error= 0;
+ JOIN *join;
DBUG_ENTER("st_select_lex_unit::cleanup");
if (cleaned)
{
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
cleaned= 1;
@@ -577,9 +584,8 @@ int st_select_lex_unit::cleanup()
free_tmp_table(thd, table);
table= 0; // Safety
}
- JOIN *join;
- SELECT_LEX *sl= first_select_in_union();
- for (; sl; sl= sl->next_select())
+
+ for (SELECT_LEX *sl= first_select_in_union(); sl; sl= sl->next_select())
{
if ((join= sl->join))
{
@@ -604,6 +610,7 @@ int st_select_lex_unit::cleanup()
error|= join->cleanup();
delete join;
}
+
DBUG_RETURN(error);
}
@@ -639,19 +646,19 @@ void st_select_lex_unit::reinit_exec_mechanism()
old_result old select_result object
RETURN
- 0 - OK
- -1 - error
+ FALSE - OK
+ TRUE - error
*/
-int st_select_lex_unit::change_result(select_subselect *result,
- select_subselect *old_result)
+bool st_select_lex_unit::change_result(select_subselect *result,
+ select_subselect *old_result)
{
- int res= 0;
+ bool res= FALSE;
for (SELECT_LEX *sl= first_select_in_union(); sl; sl= sl->next_select())
{
if (sl->join && sl->join->result == old_result)
- if ((res= sl->join->change_result(result)))
- return (res);
+ if (sl->join->change_result(result))
+ return TRUE;
}
if (fake_select_lex && fake_select_lex->join)
res= fake_select_lex->join->change_result(result);