summaryrefslogtreecommitdiff
path: root/sql/sql_union.cc
diff options
context:
space:
mode:
authorpem@mysql.com <>2003-12-01 16:14:40 +0100
committerpem@mysql.com <>2003-12-01 16:14:40 +0100
commit6e717133c5e43d45f720dff9feb5e9ff58867876 (patch)
tree024f2d18e3cf9f65db53f9f8c2d5413859781e16 /sql/sql_union.cc
parent82270288de9244ff2b1ae5a58d66add2a13d6e70 (diff)
parentf266cdabab538eeb87682af70d5e76652ee6387b (diff)
downloadmariadb-git-6e717133c5e43d45f720dff9feb5e9ff58867876.tar.gz
Merge 4.1 to 5.0
Diffstat (limited to 'sql/sql_union.cc')
-rw-r--r--sql/sql_union.cc182
1 files changed, 92 insertions, 90 deletions
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 8900d48ee4f..33204608fb1 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -25,11 +25,11 @@
#include "sql_select.h"
int mysql_union(THD *thd, LEX *lex, select_result *result,
- SELECT_LEX_UNIT *unit, bool tables_and_fields_initied)
+ SELECT_LEX_UNIT *unit)
{
DBUG_ENTER("mysql_union");
int res= 0;
- if (!(res= unit->prepare(thd, result, tables_and_fields_initied)))
+ if (!(res= unit->prepare(thd, result)))
res= unit->exec();
res|= unit->cleanup();
DBUG_RETURN(res);
@@ -59,12 +59,6 @@ select_union::~select_union()
int select_union::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
{
unit= u;
- if (not_describe && list.elements != table->fields)
- {
- my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT,
- ER(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT),MYF(0));
- return -1;
- }
return 0;
}
@@ -112,12 +106,12 @@ bool select_union::flush()
}
-int st_select_lex_unit::prepare(THD *thd, select_result *sel_result,
- bool tables_and_fields_initied)
+int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result)
{
- SELECT_LEX *lex_select_save= thd->lex->current_select;
- SELECT_LEX *select_cursor,*sl;
- DBUG_ENTER("st_select_lex_unit::prepare");
+ SELECT_LEX *lex_select_save= thd_arg->lex->current_select;
+ SELECT_LEX *sl, *first_select;
+ select_result *tmp_result;
+ DBUG_ENTER("st_select_lex_unit::prepare");
/*
result object should be reassigned even if preparing already done for
@@ -129,75 +123,32 @@ int st_select_lex_unit::prepare(THD *thd, select_result *sel_result,
DBUG_RETURN(0);
prepared= 1;
res= 0;
- found_rows_for_union= first_select_in_union()->options & OPTION_FOUND_ROWS;
- TMP_TABLE_PARAM tmp_table_param;
- t_and_f= tables_and_fields_initied;
- bzero((char *)&tmp_table_param,sizeof(TMP_TABLE_PARAM));
- thd->lex->current_select= sl= select_cursor= first_select_in_union();
+ thd_arg->lex->current_select= sl= first_select= first_select_in_union();
+ found_rows_for_union= first_select->options & OPTION_FOUND_ROWS;
+
/* Global option */
- if (t_and_f)
+
+ if (first_select->next_select())
{
- // Item list and tables will be initialized by mysql_derived
- item_list= select_cursor->item_list;
+ if (!(tmp_result= union_result= new select_union(0)))
+ goto err;
+ union_result->not_describe= 1;
+ union_result->tmp_table_param.init();
}
else
{
- item_list.empty();
- TABLE_LIST *first_table= (TABLE_LIST*) select_cursor->table_list.first;
-
- if (setup_tables(first_table) ||
- setup_wild(thd, first_table, select_cursor->item_list, 0,
- select_cursor->with_wild))
- goto err;
- List_iterator<Item> it(select_cursor->item_list);
- Item *item;
- item_list= select_cursor->item_list;
- select_cursor->with_wild= 0;
- if (select_cursor->setup_ref_array(thd,
- select_cursor->order_list.elements +
- select_cursor->group_list.elements) ||
- setup_fields(thd, select_cursor->ref_pointer_array, first_table,
- item_list, 0, 0, 1))
- goto err;
- // Item list should be fix_fielded yet another time in JOIN::prepare
- unfix_item_list(item_list);
-
- t_and_f= 1;
- while((item=it++))
- {
- item->maybe_null=1;
- if (item->type() == Item::FIELD_ITEM)
- ((class Item_field *)item)->field->table->maybe_null=1;
- }
+ tmp_result= sel_result;
+ // single select should be processed like select in p[arantses
+ first_select->braces= 1;
}
- tmp_table_param.field_count=item_list.elements;
- if (!(table= create_tmp_table(thd, &tmp_table_param, item_list,
- (ORDER*) 0, !union_option,
- 1, (select_cursor->options | thd->options |
- TMP_TABLE_ALL_COLUMNS),
- HA_POS_ERROR, (char*) "")))
- goto err;
- table->file->extra(HA_EXTRA_WRITE_CACHE);
- table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
- bzero((char*) &result_table_list,sizeof(result_table_list));
- result_table_list.db= (char*) "";
- result_table_list.real_name=result_table_list.alias= (char*) "union";
- result_table_list.table=table;
-
- if (!(union_result=new select_union(table)))
- goto err;
-
- union_result->not_describe=1;
- union_result->tmp_table_param=tmp_table_param;
-
for (;sl; sl= sl->next_select())
{
- JOIN *join= new JOIN(thd, sl->item_list,
- sl->options | thd->options | SELECT_NO_UNLOCK,
- union_result);
- thd->lex->current_select= sl;
+ JOIN *join= new JOIN(thd_arg, sl->item_list,
+ sl->options | thd_arg->options | SELECT_NO_UNLOCK,
+ tmp_result);
+ 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)
@@ -215,29 +166,80 @@ int st_select_lex_unit::prepare(THD *thd, select_result *sel_result,
(ORDER*) sl->group_list.first,
sl->having,
(ORDER*) NULL,
- sl, this, t_and_f);
- t_and_f= 0;
- if (res || thd->is_fatal_error)
+ sl, this);
+ if (res || thd_arg->is_fatal_error)
goto err;
+ if (sl == first_select)
+ {
+ types.empty();
+ List_iterator_fast<Item> it(sl->item_list);
+ Item *item_tmp;
+ while ((item_tmp= it++))
+ {
+ types.push_back(new Item_type_holder(thd_arg, item_tmp));
+ }
+
+ if (thd_arg->is_fatal_error)
+ goto err; // out of memory
+ }
+ else
+ {
+ if (types.elements != sl->item_list.elements)
+ {
+ my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT,
+ ER(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT),MYF(0));
+ goto err;
+ }
+ List_iterator_fast<Item> it(sl->item_list);
+ List_iterator_fast<Item> tp(types);
+ Item *type, *item_tmp;
+ while ((type= tp++, item_tmp= it++))
+ {
+ if (((Item_type_holder*)type)->join_types(thd_arg, item_tmp))
+ DBUG_RETURN(-1);
+ }
+ }
}
- item_list.empty();
- thd->lex->current_select= lex_select_save;
+ if (first_select->next_select())
{
- List_iterator<Item> it(select_cursor->item_list);
- Field **field;
+ union_result->tmp_table_param.field_count= types.elements;
+ if (!(table= create_tmp_table(thd_arg,
+ &union_result->tmp_table_param, types,
+ (ORDER*) 0, !union_option, 1,
+ (first_select_in_union()->options |
+ thd_arg->options |
+ TMP_TABLE_ALL_COLUMNS),
+ HA_POS_ERROR, (char*) "")))
+ goto err;
+ table->file->extra(HA_EXTRA_WRITE_CACHE);
+ table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
+ bzero((char*) &result_table_list, sizeof(result_table_list));
+ result_table_list.db= (char*) "";
+ result_table_list.real_name= result_table_list.alias= (char*) "union";
+ result_table_list.table= table;
+ union_result->set_table(table);
- for (field= table->field; *field; field++)
+ item_list.empty();
+ thd_arg->lex.current_select= lex_select_save;
{
- (void) it++;
- if (item_list.push_back(new Item_field(*field)))
- DBUG_RETURN(-1);
+ Field **field;
+ for (field= table->field; *field; field++)
+ {
+ if (item_list.push_back(new Item_field(*field)))
+ DBUG_RETURN(-1);
+ }
}
}
+ else
+ first_select->braces= 0; // remove our changes
+
+ thd_arg->lex.current_select= lex_select_save;
+
+ DBUG_RETURN(res || thd_arg->is_fatal_error ? 1 : 0);
- DBUG_RETURN(res || thd->is_fatal_error ? 1 : 0);
err:
- thd->lex->current_select= lex_select_save;
+ thd_arg->lex->current_select= lex_select_save;
DBUG_RETURN(-1);
}
@@ -372,7 +374,7 @@ int st_select_lex_unit::exec()
if (!thd->is_fatal_error) // Check if EOM
{
- ulong options= thd->options;
+ ulong options_tmp= thd->options;
thd->lex->current_select= fake_select_lex;
offset_limit_cnt= global_parameters->offset_limit;
select_limit_cnt= global_parameters->select_limit +
@@ -381,9 +383,9 @@ int st_select_lex_unit::exec()
if (select_limit_cnt < global_parameters->select_limit)
select_limit_cnt= HA_POS_ERROR; // no limit
if (select_limit_cnt == HA_POS_ERROR)
- options&= ~OPTION_FOUND_ROWS;
+ options_tmp&= ~OPTION_FOUND_ROWS;
else if (found_rows_for_union && !thd->lex->describe)
- options|= OPTION_FOUND_ROWS;
+ options_tmp|= OPTION_FOUND_ROWS;
fake_select_lex->ftfunc_list= &empty_list;
fake_select_lex->table_list.link_in_list((byte *)&result_table_list,
(byte **)
@@ -418,8 +420,8 @@ int st_select_lex_unit::exec()
global_parameters->order_list.elements,
(ORDER*)global_parameters->order_list.first,
(ORDER*) NULL, NULL, (ORDER*) NULL,
- options | SELECT_NO_UNLOCK,
- result, this, fake_select_lex, 0);
+ options_tmp | SELECT_NO_UNLOCK,
+ result, this, fake_select_lex);
if (!res)
thd->limit_found_rows = (ulonglong)table->file->records + add_rows;
/*