summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <bell@sanja.is.com.ua>2003-11-23 17:59:28 +0200
committerunknown <bell@sanja.is.com.ua>2003-11-23 17:59:28 +0200
commit105087127ed6f05c03b34f79402341cebfb8b71a (patch)
treee1e76ccec7e31e26c1b2989bbb32189db8f475f9 /sql
parentc1dd9540a4e397668040ab4027500138c238081b (diff)
parent3e21b667bcf164779674e0c08d8c1b9044acc2b5 (diff)
downloadmariadb-git-105087127ed6f05c03b34f79402341cebfb8b71a.tar.gz
Merge sanja.is.com.ua:/home/bell/mysql/bk/mysql-4.1
into sanja.is.com.ua:/home/bell/mysql/bk/work-union-4.1 sql/item.cc: Auto merged sql/item.h: Auto merged
Diffstat (limited to 'sql')
-rw-r--r--sql/field.h48
-rw-r--r--sql/item.cc121
-rw-r--r--sql/item.h32
-rw-r--r--sql/item_subselect.cc49
-rw-r--r--sql/mysql_priv.h5
-rw-r--r--sql/sql_base.cc14
-rw-r--r--sql/sql_class.h1
-rw-r--r--sql/sql_derived.cc152
-rw-r--r--sql/sql_lex.h11
-rw-r--r--sql/sql_parse.cc2
-rw-r--r--sql/sql_prepare.cc2
-rw-r--r--sql/sql_select.cc222
-rw-r--r--sql/sql_select.h2
-rw-r--r--sql/sql_union.cc154
-rw-r--r--sql/sql_update.cc2
15 files changed, 508 insertions, 309 deletions
diff --git a/sql/field.h b/sql/field.h
index 692e64d1146..ef6920f4d89 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -230,6 +230,24 @@ public:
virtual bool has_charset(void) const { return FALSE; }
virtual void set_charset(CHARSET_INFO *charset) { }
void set_warning(const unsigned int level, const unsigned int code);
+ /*
+ number which describe preferences of field type converion,
+ for example, if we have int and float, float is prefered as more general
+
+ ennumiration begins from:
+ 100 for int types
+ 300 for float point
+ 500 time/date
+ 700 string
+ */
+ virtual uint convert_order()= 0;
+ /*
+ Is this type is compatible with given
+ (given can be stored in it)
+ Should take care only of types 'less' then current
+ */
+ virtual bool convert_order_compatible(uint order) { return 0; }
+
friend bool reopen_table(THD *,struct st_table *,bool);
friend int cre_myisam(my_string name, register TABLE *form, uint options,
ulonglong auto_increment_value);
@@ -334,6 +352,7 @@ public:
void overflow(bool negative);
bool zero_pack() const { return 0; }
void sql_type(String &str) const;
+ uint convert_order() { return 130; }
};
@@ -369,6 +388,7 @@ public:
void sort_string(char *buff,uint length);
uint32 pack_length() const { return 1; }
void sql_type(String &str) const;
+ uint convert_order() { return 100; }
};
@@ -404,6 +424,7 @@ public:
void sort_string(char *buff,uint length);
uint32 pack_length() const { return 2; }
void sql_type(String &str) const;
+ uint convert_order() { return 101; }
};
@@ -434,6 +455,7 @@ public:
void sort_string(char *buff,uint length);
uint32 pack_length() const { return 3; }
void sql_type(String &str) const;
+ uint convert_order() { return 102; }
};
@@ -469,6 +491,7 @@ public:
void sort_string(char *buff,uint length);
uint32 pack_length() const { return 4; }
void sql_type(String &str) const;
+ uint convert_order() { return 103; }
};
@@ -507,6 +530,7 @@ public:
uint32 pack_length() const { return 8; }
void sql_type(String &str) const;
bool store_for_compare() { return 1; }
+ uint convert_order() { return 104; }
};
#endif
@@ -540,6 +564,7 @@ public:
void sort_string(char *buff,uint length);
uint32 pack_length() const { return sizeof(float); }
void sql_type(String &str) const;
+ uint convert_order() { return 300; }
};
@@ -573,6 +598,7 @@ public:
void sort_string(char *buff,uint length);
uint32 pack_length() const { return sizeof(double); }
void sql_type(String &str) const;
+ uint convert_order() { return 301; }
};
@@ -606,6 +632,7 @@ public:
uint32 pack_length() const { return 0; }
void sql_type(String &str) const;
uint size_of() const { return sizeof(*this); }
+ uint convert_order() { return 0; }
};
@@ -649,6 +676,8 @@ public:
}
bool get_date(TIME *ltime,uint fuzzydate);
bool get_time(TIME *ltime);
+ uint convert_order() { return 520; }
+ bool convert_order_compatible(uint ord) { return ord<520; }
};
@@ -674,6 +703,8 @@ public:
String *val_str(String*,String *);
bool send_binary(Protocol *protocol);
void sql_type(String &str) const;
+ uint convert_order() { return 501; }
+ bool convert_order_compatible(uint ord) { return ord<520; }
};
@@ -706,6 +737,8 @@ public:
void sql_type(String &str) const;
bool store_for_compare() { return 1; }
bool zero_pack() const { return 1; }
+ uint convert_order() { return 502; }
+ bool convert_order_compatible(uint ord) { return ord<520; }
};
class Field_newdate :public Field_str {
@@ -737,6 +770,8 @@ public:
bool zero_pack() const { return 1; }
bool get_date(TIME *ltime,uint fuzzydate);
bool get_time(TIME *ltime);
+ uint convert_order() { return 503; }
+ bool convert_order_compatible(uint ord) { return ord<520; }
};
@@ -770,6 +805,8 @@ public:
void sql_type(String &str) const;
bool store_for_compare() { return 1; }
bool zero_pack() const { return 1; }
+ uint convert_order() { return 504; }
+ bool convert_order_compatible(uint ord) { return ord<520; }
};
@@ -807,6 +844,8 @@ public:
bool zero_pack() const { return 1; }
bool get_date(TIME *ltime,uint fuzzydate);
bool get_time(TIME *ltime);
+ uint convert_order() { return 530; }
+ bool convert_order_compatible(uint ord) { return ord<=501; }
};
@@ -851,6 +890,7 @@ public:
uint size_of() const { return sizeof(*this); }
enum_field_types real_type() const { return FIELD_TYPE_STRING; }
bool has_charset(void) const { return TRUE; }
+ uint convert_order() { return 700; }
};
@@ -894,6 +934,7 @@ public:
uint size_of() const { return sizeof(*this); }
enum_field_types real_type() const { return FIELD_TYPE_VAR_STRING; }
bool has_charset(void) const { return TRUE; }
+ uint convert_order() { return 701; }
};
@@ -983,6 +1024,7 @@ public:
uint size_of() const { return sizeof(*this); }
bool has_charset(void) const
{ return charset() == &my_charset_bin ? FALSE : TRUE; }
+ uint convert_order() { return 701; }
};
@@ -1011,6 +1053,8 @@ public:
void get_key_image(char *buff,uint length, CHARSET_INFO *cs,imagetype type);
void set_key_image(char *buff,uint length, CHARSET_INFO *cs);
+ uint convert_order() { return 750; }
+ bool convert_order_compatible(uint ord) { return ord < 750; };
};
@@ -1052,6 +1096,8 @@ public:
bool optimize_range(uint idx) { return 0; }
bool eq_def(Field *field);
bool has_charset(void) const { return TRUE; }
+ uint convert_order() { return 30; }
+ bool convert_order_compatible(uint ord) { return ord < 30; };
};
@@ -1077,6 +1123,8 @@ public:
void sql_type(String &str) const;
enum_field_types real_type() const { return FIELD_TYPE_SET; }
bool has_charset(void) const { return TRUE; }
+ uint convert_order() { return 40; }
+ bool convert_order_compatible(uint ord) { return ord < 40; };
};
diff --git a/sql/item.cc b/sql/item.cc
index 1d43351688b..e5a9f9db740 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -312,7 +312,7 @@ void Item_field::set_field(Field *field_par)
const char *Item_ident::full_name() const
{
char *tmp;
- if (!table_name)
+ if (!table_name || !field_name)
return field_name ? field_name : name ? name : "tmp_field";
if (db_name && db_name[0])
{
@@ -1881,6 +1881,8 @@ void Item_cache_str::store(Item *item)
}
collation.set(item->collation);
}
+
+
double Item_cache_str::val()
{
int err;
@@ -1890,6 +1892,8 @@ double Item_cache_str::val()
else
return (double)0;
}
+
+
longlong Item_cache_str::val_int()
{
int err;
@@ -1900,6 +1904,7 @@ longlong Item_cache_str::val_int()
return (longlong)0;
}
+
bool Item_cache_row::allocate(uint num)
{
item_count= num;
@@ -1908,6 +1913,7 @@ bool Item_cache_row::allocate(uint num)
(Item_cache **) thd->calloc(sizeof(Item_cache *)*item_count)));
}
+
bool Item_cache_row::setup(Item * item)
{
example= item;
@@ -1924,6 +1930,7 @@ bool Item_cache_row::setup(Item * item)
return 0;
}
+
void Item_cache_row::store(Item * item)
{
null_value= 0;
@@ -1935,6 +1942,7 @@ void Item_cache_row::store(Item * item)
}
}
+
void Item_cache_row::illegal_method_call(const char *method)
{
DBUG_ENTER("Item_cache_row::illegal_method_call");
@@ -1944,6 +1952,7 @@ void Item_cache_row::illegal_method_call(const char *method)
DBUG_VOID_RETURN;
}
+
bool Item_cache_row::check_cols(uint c)
{
if (c != item_count)
@@ -1954,6 +1963,7 @@ bool Item_cache_row::check_cols(uint c)
return 0;
}
+
bool Item_cache_row::null_inside()
{
for (uint i= 0; i < item_count; i++)
@@ -1973,6 +1983,7 @@ bool Item_cache_row::null_inside()
return 0;
}
+
void Item_cache_row::bring_value()
{
for (uint i= 0; i < item_count; i++)
@@ -1980,6 +1991,114 @@ void Item_cache_row::bring_value()
return;
}
+
+Item_type_holder::Item_type_holder(THD *thd, Item *item)
+ :Item(thd, *item), item_type(item->result_type())
+{
+ DBUG_ASSERT(item->fixed);
+ if (item->type() == Item::FIELD_ITEM)
+ {
+ Item_field *fitem= (Item_field*) item;
+ field_example= (Field*) thd->memdup((const char*)fitem->field,
+ fitem->field->size_of());
+ }
+ else
+ field_example= 0;
+}
+
+
+// STRING_RESULT, REAL_RESULT, INT_RESULT, ROW_RESULT
+static Item_result type_convertor[4][4]=
+{{STRING_RESULT, STRING_RESULT, STRING_RESULT, ROW_RESULT},
+ {STRING_RESULT, REAL_RESULT, REAL_RESULT, ROW_RESULT},
+ {STRING_RESULT, REAL_RESULT, INT_RESULT, ROW_RESULT},
+ {ROW_RESULT, ROW_RESULT, ROW_RESULT, ROW_RESULT}};
+
+void Item_type_holder::join_types(THD *thd, Item *item)
+{
+ bool change_field= 0, skip_store_field= 0;
+ Item_result new_type= type_convertor[item_type][item->result_type()];
+
+ // we have both fields
+ if (field_example && item->type() == Item::FIELD_ITEM)
+ {
+ Field *field= ((Item_field *)item)->field;
+
+ // is new field better
+ if ((change_field=
+ field_example->convert_order() < field->convert_order()))
+ {
+ // is it compatible?
+ if (field->convert_order_compatible(field_example->convert_order()))
+ skip_store_field= 1;
+ }
+ else
+ {
+ /*
+ if old field can't store value of 'worse' new field we will make
+ decision about result field tipe based only on Item result type
+ */
+ if (field_example->convert_order_compatible(field->convert_order()))
+ skip_store_field= 1;
+ }
+ }
+
+ // size/type should be changed
+ if (change_field ||
+ (new_type != item_type) ||
+ (max_length < item->max_length) ||
+ ((new_type == INT_RESULT) &&
+ (decimals < item->decimals)) ||
+ (!maybe_null && item->maybe_null))
+ {
+ // new field has some parameters worse then current
+ skip_store_field|= (change_field &&
+ (max_length > item->max_length) ||
+ ((new_type == INT_RESULT) &&
+ (decimals > item->decimals)) ||
+ (maybe_null && !item->maybe_null));
+ if (skip_store_field || item->type() != Item::FIELD_ITEM)
+ field_example= 0;
+ else
+ {
+ /*
+ we do not need following, because we use mem_root
+ if (field_example)
+ thd->free(field_example)
+ */
+ Item_field *fitem= (Item_field*) item;
+ field_example= (Field*) thd->memdup((const char*)fitem->field,
+ fitem->field->size_of());
+ }
+ max_length= max(max_length, item->max_length);
+ decimals= max(decimals, item->decimals);
+ maybe_null|= item->maybe_null;
+ item_type= new_type;
+ }
+ DBUG_ASSERT(item_type != ROW_RESULT);
+}
+
+
+double Item_type_holder::val()
+{
+ DBUG_ASSERT(0); // should never be called
+ return 0.0;
+}
+
+
+longlong Item_type_holder::val_int()
+{
+ DBUG_ASSERT(0); // should never be called
+ return 0;
+}
+
+
+String *Item_type_holder::val_str(String*)
+{
+ DBUG_ASSERT(0); // should never be called
+ return 0;
+}
+
/*****************************************************************************
** Instantiate templates
*****************************************************************************/
diff --git a/sql/item.h b/sql/item.h
index 53db177b360..c79964f5811 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -98,7 +98,7 @@ public:
COPY_STR_ITEM, FIELD_AVG_ITEM, DEFAULT_VALUE_ITEM,
PROC_ITEM,COND_ITEM, REF_ITEM, FIELD_STD_ITEM,
FIELD_VARIANCE_ITEM, INSERT_VALUE_ITEM,
- SUBSELECT_ITEM, ROW_ITEM, CACHE_ITEM};
+ SUBSELECT_ITEM, ROW_ITEM, CACHE_ITEM, TYPE_HOLDER};
enum cond_result { COND_UNDEF,COND_OK,COND_TRUE,COND_FALSE };
@@ -390,17 +390,17 @@ class Item_int :public Item
public:
const longlong value;
Item_int(int32 i,uint length=11) :value((longlong) i)
- { max_length=length;}
+ { max_length=length; fixed= 1; }
#ifdef HAVE_LONG_LONG
Item_int(longlong i,uint length=21) :value(i)
- { max_length=length;}
+ { max_length=length; fixed= 1;}
#endif
Item_int(const char *str_arg,longlong i,uint length) :value(i)
- { max_length=length; name=(char*) str_arg;}
+ { max_length=length; name=(char*) str_arg; fixed= 1; }
Item_int(const char *str_arg) :
value(str_arg[0] == '-' ? strtoll(str_arg,(char**) 0,10) :
(longlong) strtoull(str_arg,(char**) 0,10))
- { max_length= (uint) strlen(str_arg); name=(char*) str_arg;}
+ { max_length= (uint) strlen(str_arg); name=(char*) str_arg; fixed= 1; }
enum Type type() const { return INT_ITEM; }
enum Item_result result_type () const { return INT_RESULT; }
enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }
@@ -988,6 +988,28 @@ public:
void bring_value();
};
+
+/*
+ Used to store type. name, length of Item for UNIONS & derived table
+*/
+class Item_type_holder: public Item
+{
+protected:
+ Item_result item_type;
+ Field *field_example;
+public:
+ Item_type_holder(THD*, Item*);
+
+ Item_result result_type () const { return item_type; }
+ enum Type type() const { return TYPE_HOLDER; }
+ double val();
+ longlong val_int();
+ String *val_str(String*);
+ void join_types(THD *thd, Item *);
+ Field *example() { return field_example; }
+};
+
+
extern Item_buff *new_Item_buff(Item *item);
extern Item_result item_cmp_type(Item_result a,Item_result b);
extern Item *resolve_const_item(Item *item,Item *cmp_item);
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index a60a35aac6b..367400d6b0b 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -924,7 +924,7 @@ int subselect_single_select_engine::prepare()
(ORDER*) select_lex->group_list.first,
select_lex->having,
(ORDER*) 0, select_lex,
- select_lex->master_unit(), 0))
+ select_lex->master_unit()))
return 1;
thd->lex.current_select= save_select;
return 0;
@@ -932,7 +932,7 @@ int subselect_single_select_engine::prepare()
int subselect_union_engine::prepare()
{
- return unit->prepare(thd, result, 0);
+ return unit->prepare(thd, result);
}
int subselect_uniquesubquery_engine::prepare()
@@ -942,12 +942,12 @@ int subselect_uniquesubquery_engine::prepare()
return 1;
}
-static Item_result set_row(SELECT_LEX *select_lex, Item * item,
+static Item_result set_row(List<Item> &item_list, Item *item,
Item_cache **row, bool *maybe_null)
{
Item_result res_type= STRING_RESULT;
Item *sel_item;
- List_iterator_fast<Item> li(select_lex->item_list);
+ List_iterator_fast<Item> li(item_list);
for (uint i= 0; (sel_item= li++); i++)
{
item->max_length= sel_item->max_length;
@@ -962,7 +962,7 @@ static Item_result set_row(SELECT_LEX *select_lex, Item * item,
row[i]->collation.set(sel_item->collation);
}
}
- if (select_lex->item_list.elements > 1)
+ if (item_list.elements > 1)
res_type= ROW_RESULT;
return res_type;
}
@@ -970,7 +970,7 @@ static Item_result set_row(SELECT_LEX *select_lex, Item * item,
void subselect_single_select_engine::fix_length_and_dec(Item_cache **row)
{
DBUG_ASSERT(row || select_lex->item_list.elements==1);
- res_type= set_row(select_lex, item, row, &maybe_null);
+ res_type= set_row(select_lex->item_list, item, row, &maybe_null);
item->collation.set(row[0]->collation);
if (cols() != 1)
maybe_null= 0;
@@ -981,44 +981,11 @@ void subselect_union_engine::fix_length_and_dec(Item_cache **row)
DBUG_ASSERT(row || unit->first_select()->item_list.elements==1);
if (unit->first_select()->item_list.elements == 1)
- {
- uint32 mlen= 0, len;
- Item *sel_item= 0;
- for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select())
- {
- List_iterator_fast<Item> li(sl->item_list);
- Item *s_item= li++;
- if ((len= s_item->max_length) > mlen)
- mlen= len;
- if (!sel_item)
- sel_item= s_item;
- maybe_null= s_item->maybe_null;
- }
- item->max_length= mlen;
- res_type= sel_item->result_type();
- item->decimals= sel_item->decimals;
- if (row)
- {
- if (!(row[0]= Item_cache::get_cache(res_type)))
- return;
- row[0]->set_len_n_dec(mlen, sel_item->decimals);
- }
- }
+ res_type= set_row(unit->types, item, row, &maybe_null);
else
{
- SELECT_LEX *sl= unit->first_select();
bool fake= 0;
- res_type= set_row(sl, item, row, &fake);
- for (sl= sl->next_select(); sl; sl= sl->next_select())
- {
- List_iterator_fast<Item> li(sl->item_list);
- Item *sel_item;
- for (uint i= 0; (sel_item= li++); i++)
- {
- if (sel_item->max_length > row[i]->max_length)
- row[i]->max_length= sel_item->max_length;
- }
- }
+ res_type= set_row(unit->types, item, row, &fake);
}
}
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index b9032381c45..5cf352aff99 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -482,7 +482,7 @@ int mysql_select(THD *thd, Item ***rref_pointer_array,
COND *conds, uint og_num, ORDER *order, ORDER *group,
Item *having, ORDER *proc_param, ulong select_type,
select_result *result, SELECT_LEX_UNIT *unit,
- SELECT_LEX *select_lex, bool tables_and_fields_initied);
+ SELECT_LEX *select_lex);
void free_underlaid_joins(THD *thd, SELECT_LEX *select);
void fix_tables_pointers(SELECT_LEX *select_lex);
void fix_tables_pointers(SELECT_LEX_UNIT *select_lex);
@@ -491,7 +491,7 @@ int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit,
int mysql_explain_select(THD *thd, SELECT_LEX *sl, char const *type,
select_result *result);
int mysql_union(THD *thd, LEX *lex, select_result *result,
- SELECT_LEX_UNIT *unit, bool tables_and_fields_initied);
+ SELECT_LEX_UNIT *unit);
int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, TABLE_LIST *t);
Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
Item ***copy_func, Field **from_field,
@@ -675,7 +675,6 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
int setup_fields(THD *thd, Item** ref_pointer_array, TABLE_LIST *tables,
List<Item> &item, bool set_query_id,
List<Item> *sum_func_list, bool allow_sum_func);
-void unfix_item_list(List<Item> item_list);
int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds);
int setup_ftfuncs(SELECT_LEX* select);
int init_ftfuncs(THD *thd, SELECT_LEX* select, bool no_order);
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 7a657841845..775aa1cd43f 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -2023,20 +2023,6 @@ int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
DBUG_RETURN(test(thd->net.report_error));
}
-/*
- Mark all items in list as not fixed (0 assigned to 'fixed' field)
-
- SYNOPSYS
- unfix_item_list()
- item_list - list of items
-*/
-void unfix_item_list(List<Item> item_list)
-{
- Item *item;
- List_iterator_fast<Item> it(item_list);
- while ((item= it++))
- item->walk(&Item::remove_fixed, 0);
-}
/*
Remap table numbers if INSERT ... SELECT
diff --git a/sql/sql_class.h b/sql/sql_class.h
index b19caf057e6..36faeae8f57 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -946,6 +946,7 @@ class select_union :public select_result {
bool send_data(List<Item> &items);
bool send_eof();
bool flush();
+ void set_table(TABLE *tbl) { table= tbl; }
};
/* Base subselect interface class */
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index 719686a56c3..591c6579a46 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -62,16 +62,15 @@
int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
TABLE_LIST *org_table_list)
{
- SELECT_LEX *select_cursor= unit->first_select();
- List<Item> item_list;
+ SELECT_LEX *first_select= unit->first_select();
TABLE *table;
int res;
select_union *derived_result;
- TABLE_LIST *tables= (TABLE_LIST *)select_cursor->table_list.first;
+ TABLE_LIST *tables= (TABLE_LIST *)first_select->table_list.first;
TMP_TABLE_PARAM tmp_table_param;
- bool is_union= select_cursor->next_select() &&
- select_cursor->next_select()->linkage == UNION_TYPE;
- bool is_subsel= select_cursor->first_inner_unit() ? 1: 0;
+ bool is_union= first_select->next_select() &&
+ first_select->next_select()->linkage == UNION_TYPE;
+ bool is_subsel= first_select->first_inner_unit() ? 1: 0;
SELECT_LEX *save_current_select= lex->current_select;
DBUG_ENTER("mysql_derived");
@@ -112,16 +111,12 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
fix_tables_pointers(unit);
}
- lex->current_select= select_cursor;
- TABLE_LIST *first_table= (TABLE_LIST*) select_cursor->table_list.first;
- /* Setting up. A must if a join or IGNORE, USE or similar are utilised */
- if (setup_tables(first_table) ||
- setup_wild(thd, first_table, select_cursor->item_list, 0,
- select_cursor->with_wild))
- {
- res= -1;
+ if(!(derived_result= new select_union(0)))
+ DBUG_RETURN(1); // out of memory
+
+ // st_select_lex_unit::prepare coppectly work for single select
+ if ((res= unit->prepare(thd, derived_result)))
goto exit;
- }
/*
This is done in order to redo all field optimisations when any of the
@@ -133,30 +128,16 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
cursor->table->clear_query_id= 1;
}
- 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))
- {
- res= -1;
- goto exit;
- }
- // Item list should be fix_fielded yet another time in JOIN::prepare
- unfix_item_list(item_list);
-
bzero((char*) &tmp_table_param,sizeof(tmp_table_param));
- tmp_table_param.field_count= item_list.elements;
+ tmp_table_param.field_count= unit->types.elements;
/*
Temp table is created so that it hounours if UNION without ALL is to be
processed
*/
- if (!(table= create_tmp_table(thd, &tmp_table_param, item_list,
+ if (!(table= create_tmp_table(thd, &tmp_table_param, unit->types,
(ORDER*) 0,
is_union && !unit->union_option, 1,
- (select_cursor->options | thd->options |
+ (first_select->options | thd->options |
TMP_TABLE_ALL_COLUMNS),
HA_POS_ERROR,
org_table_list->alias)))
@@ -164,70 +145,69 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
res= -1;
goto exit;
}
-
- if ((derived_result=new select_union(table)))
+ derived_result->set_table(table);
+ derived_result->tmp_table_param=tmp_table_param;
+
+ unit->offset_limit_cnt= first_select->offset_limit;
+ unit->select_limit_cnt= first_select->select_limit+
+ first_select->offset_limit;
+ if (unit->select_limit_cnt < first_select->select_limit)
+ unit->select_limit_cnt= HA_POS_ERROR;
+ if (unit->select_limit_cnt == HA_POS_ERROR)
+ first_select->options&= ~OPTION_FOUND_ROWS;
+
+ if (is_union)
+ res= mysql_union(thd, lex, derived_result, unit);
+ else
+ res= mysql_select(thd, &first_select->ref_pointer_array,
+ (TABLE_LIST*) first_select->table_list.first,
+ first_select->with_wild,
+ first_select->item_list, first_select->where,
+ (first_select->order_list.elements+
+ first_select->group_list.elements),
+ (ORDER *) first_select->order_list.first,
+ (ORDER *) first_select->group_list.first,
+ first_select->having, (ORDER*) NULL,
+ (first_select->options | thd->options |
+ SELECT_NO_UNLOCK),
+ derived_result, unit, first_select);
+
+ if (!res)
{
- derived_result->tmp_table_param=tmp_table_param;
- unit->offset_limit_cnt= select_cursor->offset_limit;
- unit->select_limit_cnt= select_cursor->select_limit+
- select_cursor->offset_limit;
- if (unit->select_limit_cnt < select_cursor->select_limit)
- unit->select_limit_cnt= HA_POS_ERROR;
- if (unit->select_limit_cnt == HA_POS_ERROR)
- select_cursor->options&= ~OPTION_FOUND_ROWS;
-
- if (is_union)
- res= mysql_union(thd, lex, derived_result, unit, 1);
+ /*
+ Here we entirely fix both TABLE_LIST and list of SELECT's as
+ there were no derived tables
+ */
+ if (derived_result->flush())
+ res= 1;
else
- res= mysql_select(thd, &select_cursor->ref_pointer_array,
- (TABLE_LIST*) select_cursor->table_list.first,
- select_cursor->with_wild,
- select_cursor->item_list, select_cursor->where,
- (select_cursor->order_list.elements+
- select_cursor->group_list.elements),
- (ORDER *) select_cursor->order_list.first,
- (ORDER *) select_cursor->group_list.first,
- select_cursor->having, (ORDER*) NULL,
- (select_cursor->options | thd->options |
- SELECT_NO_UNLOCK),
- derived_result, unit, select_cursor, 1);
-
- if (!res)
{
- /*
- Here we entirely fix both TABLE_LIST and list of SELECT's as
- there were no derived tables
- */
- if (derived_result->flush())
- res= 1;
- else
- {
- org_table_list->real_name=table->real_name;
- org_table_list->table=table;
- table->derived_select_number= select_cursor->select_number;
- table->tmp_table= TMP_TABLE;
+ org_table_list->real_name=table->real_name;
+ org_table_list->table=table;
+ table->derived_select_number= first_select->select_number;
+ table->tmp_table= TMP_TABLE;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
- org_table_list->grant.privilege= SELECT_ACL;
+ org_table_list->grant.privilege= SELECT_ACL;
#endif
- if (lex->describe)
+ if (lex->describe)
+ {
+ // to fix a problem in EXPLAIN
+ if (tables)
{
- // to fix a problem in EXPLAIN
- if (tables)
- {
- for (TABLE_LIST *cursor= tables; cursor; cursor= cursor->next)
- if (cursor->table_list)
- cursor->table_list->table=cursor->table;
- }
+ for (TABLE_LIST *cursor= tables; cursor; cursor= cursor->next)
+ if (cursor->table_list)
+ cursor->table_list->table=cursor->table;
}
- else
- unit->exclude_tree();
- org_table_list->db= (char *)"";
- // Force read of table stats in the optimizer
- table->file->info(HA_STATUS_VARIABLE);
}
+ else
+ unit->exclude_tree();
+ org_table_list->db= (char *)"";
+ // Force read of table stats in the optimizer
+ table->file->info(HA_STATUS_VARIABLE);
}
- delete derived_result;
}
+ delete derived_result;
+
if (res)
free_tmp_table(thd, table);
else
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index d2345165eb9..29301053c59 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -295,7 +295,6 @@ class JOIN;
class select_union;
class st_select_lex_unit: public st_select_lex_node {
protected:
- List<Item> item_list;
TABLE_LIST result_table_list;
select_union *union_result;
TABLE *table; /* temporary table using for appending UNION results */
@@ -305,9 +304,13 @@ protected:
ulong found_rows_for_union;
bool prepared, // prepare phase already performed for UNION (unit)
optimized, // optimize phase already performed for UNION (unit)
- executed, // already executed
- t_and_f; // used for transferring tables_and_fields_initied UNIT:: methods
+ executed; // already executed
+
public:
+ // list of fields which points to temporary table for union
+ List<Item> item_list;
+ // list of types of items inside union (used for union & derived tables)
+ List<Item> types;
/*
Pointer to 'last' select or pointer to unit where stored
global parameters for union
@@ -342,7 +345,7 @@ public:
void exclude_tree();
/* UNION methods */
- int prepare(THD *thd, select_result *result, bool tables_and_fields_initied);
+ int prepare(THD *thd, select_result *result);
int exec();
int cleanup();
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 9f4b10682ba..d5a15de422d 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -2716,7 +2716,7 @@ mysql_execute_command(THD *thd)
(ORDER *)NULL,
select_lex->options | thd->options |
SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK,
- result, unit, select_lex, 0);
+ result, unit, select_lex);
if (thd->net.report_error)
res= -1;
delete result;
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 354214a4da5..69517b171cb 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -682,7 +682,7 @@ static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables,
if (join->prepare(&select_lex->ref_pointer_array, tables,
wild_num, conds, og_num, order, group, having, proc,
- select_lex, unit, 0))
+ select_lex, unit))
DBUG_RETURN(1);
if (send_prep_stmt(stmt, fields.elements) ||
thd->protocol_simple.send_fields(&fields, 0) ||
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 44b403c0bb1..ba4dd9f856e 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -177,7 +177,7 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
fix_tables_pointers(lex->all_selects_list);
if (select_lex->next_select())
- res=mysql_union(thd, lex, result, &lex->unit, 0);
+ res=mysql_union(thd, lex, result, &lex->unit);
else
res= mysql_select(thd, &select_lex->ref_pointer_array,
(TABLE_LIST*) select_lex->table_list.first,
@@ -190,7 +190,7 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
select_lex->having,
(ORDER*) lex->proc_list.first,
select_lex->options | thd->options,
- result, &(lex->unit), &(lex->select_lex), 0);
+ result, &(lex->unit), &(lex->select_lex));
/* Don't set res if it's -1 as we may want this later */
DBUG_PRINT("info",("res: %d report_error: %d", res,
@@ -285,8 +285,7 @@ JOIN::prepare(Item ***rref_pointer_array,
ORDER *order_init, ORDER *group_init,
Item *having_init,
ORDER *proc_param_init, SELECT_LEX *select,
- SELECT_LEX_UNIT *unit,
- bool tables_and_fields_initied)
+ SELECT_LEX_UNIT *unit)
{
DBUG_ENTER("JOIN::prepare");
@@ -302,10 +301,8 @@ JOIN::prepare(Item ***rref_pointer_array,
/* Check that all tables, fields, conds and order are ok */
- if ((tables_and_fields_initied ? 0 : (setup_tables(tables_list) ||
- setup_wild(thd, tables_list,
- fields_list,
- &all_fields, wild_num))) ||
+ if (setup_tables(tables_list) ||
+ 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,
&all_fields, 1) ||
@@ -1536,7 +1533,7 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
COND *conds, uint og_num, ORDER *order, ORDER *group,
Item *having, ORDER *proc_param, ulong select_options,
select_result *result, SELECT_LEX_UNIT *unit,
- SELECT_LEX *select_lex, bool tables_and_fields_initied)
+ SELECT_LEX *select_lex)
{
int err;
bool free_join= 1;
@@ -1546,26 +1543,31 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
if (select_lex->join != 0)
{
join= select_lex->join;
- if (select_lex->linkage != GLOBAL_OPTIONS_TYPE)
+ // is it single SELECT in derived table, called in derived table creation
+ if (select_lex->linkage != DERIVED_TABLE_TYPE ||
+ (select_options & SELECT_DESCRIBE))
{
- //here is EXPLAIN of subselect or derived table
- join->result= result;
- if (!join->procedure && result->prepare(join->fields_list, unit))
+ if (select_lex->linkage != GLOBAL_OPTIONS_TYPE)
{
- DBUG_RETURN(-1);
+ //here is EXPLAIN of subselect or derived table
+ join->result= result;
+ if (!join->procedure && result->prepare(join->fields_list, unit))
+ {
+ DBUG_RETURN(-1);
+ }
}
- }
- else
- {
- if (join->prepare(rref_pointer_array, tables, wild_num,
- conds, og_num, order, group, having, proc_param,
- select_lex, unit, tables_and_fields_initied))
+ else
{
- goto err;
+ if (join->prepare(rref_pointer_array, tables, wild_num,
+ conds, og_num, order, group, having, proc_param,
+ select_lex, unit))
+ {
+ goto err;
+ }
}
+ free_join= 0;
}
join->select_options= select_options;
- free_join= 0;
}
else
{
@@ -1574,7 +1576,7 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
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, tables_and_fields_initied))
+ select_lex, unit))
{
goto err;
}
@@ -4546,6 +4548,115 @@ const_expression_in_where(COND *cond, Item *comp_item, Item **const_item)
****************************************************************************/
/*
+ Create field for temporary table from given field
+
+ SYNOPSIS
+ create_tmp_field_from_field()
+ thd Thread handler
+ org_field field from which new field will be created
+ item Item to create a field for
+ table Temporary table
+ modify_item 1 if item->result_field should point to new item.
+ This is relevent for how fill_record() is going to
+ work:
+ If modify_item is 1 then fill_record() will update
+ the record in the original table.
+ If modify_item is 0 then fill_record() will update
+ the temporary table
+
+ RETURN
+ 0 on error
+ new_created field
+*/
+static Field* create_tmp_field_from_field(THD *thd,
+ Field* org_field,
+ Item *item,
+ TABLE *table,
+ bool modify_item)
+{
+ Field *new_field;
+
+ // The following should always be true
+ if ((new_field= org_field->new_field(&thd->mem_root,table)))
+ {
+ if (modify_item)
+ ((Item_field *)item)->result_field= new_field;
+ else
+ new_field->field_name= item->name;
+ if (org_field->maybe_null())
+ new_field->flags&= ~NOT_NULL_FLAG; // Because of outer join
+ if (org_field->type() == FIELD_TYPE_VAR_STRING)
+ table->db_create_options|= HA_OPTION_PACK_RECORD;
+ }
+ return new_field;
+}
+
+/*
+ Create field for temporary table using type of given item
+
+ SYNOPSIS
+ create_tmp_field_from_item()
+ thd Thread handler
+ item Item to create a field for
+ table Temporary table
+ copy_func If set and item is a function, store copy of item
+ in this array
+ modify_item 1 if item->result_field should point to new item.
+ This is relevent for how fill_record() is going to
+ work:
+ If modify_item is 1 then fill_record() will update
+ the record in the original table.
+ If modify_item is 0 then fill_record() will update
+ the temporary table
+
+ RETURN
+ 0 on error
+ new_created field
+*/
+static Field* create_tmp_field_from_item(THD *thd,
+ Item *item,
+ TABLE *table,
+ Item ***copy_func,
+ bool modify_item)
+{
+ bool maybe_null=item->maybe_null;
+ Field *new_field;
+ LINT_INIT(new_field);
+
+ switch (item->result_type()) {
+ case REAL_RESULT:
+ new_field=new Field_double(item->max_length, maybe_null,
+ item->name, table, item->decimals);
+ break;
+ case INT_RESULT:
+ new_field=new Field_longlong(item->max_length, maybe_null,
+ item->name, table, item->unsigned_flag);
+ break;
+ case STRING_RESULT:
+ if (item->max_length > 255)
+ new_field= new Field_blob(item->max_length, maybe_null,
+ item->name, table,
+ item->collation.collation);
+ else
+ new_field= new Field_string(item->max_length, maybe_null,
+ item->name, table,
+ item->collation.collation);
+ break;
+ case ROW_RESULT:
+ default:
+ // This case should never be choosen
+ DBUG_ASSERT(0);
+ new_field= 0; // to satisfy compiler (uninitialized variable)
+ break;
+ }
+ if (copy_func && item->is_result_field())
+ *((*copy_func)++) = item; // Save for copy_funcs
+ if (modify_item)
+ item->set_result_field(new_field);
+ return new_field;
+}
+
+/*
Create field for temporary table
SYNOPSIS
@@ -4556,6 +4667,8 @@ const_expression_in_where(COND *cond, Item *comp_item, Item **const_item)
type Type of item (normally item->type)
copy_func If set and item is a function, store copy of item
in this array
+ from_field if field will be created using other field as example,
+ pointer example field will be written here
group 1 if we are going to do a relative group by on result
modify_item 1 if item->result_field should point to new item.
This is relevent for how fill_record() is going to
@@ -4622,24 +4735,9 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
return 0; // Error
}
case Item::FIELD_ITEM:
- {
- Field *org_field=((Item_field*) item)->field,*new_field;
-
- *from_field=org_field;
- // The following should always be true
- if ((new_field= org_field->new_field(&thd->mem_root,table)))
- {
- if (modify_item)
- ((Item_field*) item)->result_field= new_field;
- else
- new_field->field_name=item->name;
- if (org_field->maybe_null())
- new_field->flags&= ~NOT_NULL_FLAG; // Because of outer join
- if (org_field->type()==FIELD_TYPE_VAR_STRING)
- table->db_create_options|= HA_OPTION_PACK_RECORD;
- }
- return new_field;
- }
+ return create_tmp_field_from_field(thd, (*from_field=
+ ((Item_field*) item)->field),
+ item, table, modify_item);
case Item::FUNC_ITEM:
case Item::COND_ITEM:
case Item::FIELD_AVG_ITEM:
@@ -4653,40 +4751,14 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
case Item::REF_ITEM:
case Item::NULL_ITEM:
case Item::VARBIN_ITEM:
+ return create_tmp_field_from_item(thd, item, table,
+ copy_func, modify_item);
+ case Item::TYPE_HOLDER:
{
- bool maybe_null=item->maybe_null;
- Field *new_field;
- LINT_INIT(new_field);
-
- switch (item->result_type()) {
- case REAL_RESULT:
- new_field=new Field_double(item->max_length,maybe_null,
- item->name,table,item->decimals);
- break;
- case INT_RESULT:
- new_field=new Field_longlong(item->max_length,maybe_null,
- item->name,table, item->unsigned_flag);
- break;
- case STRING_RESULT:
- if (item->max_length > 255)
- new_field= new Field_blob(item->max_length,maybe_null,
- item->name,table,item->collation.collation);
- else
- new_field= new Field_string(item->max_length,maybe_null,
- item->name,table,item->collation.collation);
- break;
- case ROW_RESULT:
- default:
- // This case should never be choosen
- DBUG_ASSERT(0);
- new_field= 0; // to satisfy compiler (uninitialized variable)
- break;
- }
- if (copy_func && item->is_result_field())
- *((*copy_func)++) = item; // Save for copy_funcs
- if (modify_item)
- item->set_result_field(new_field);
- return new_field;
+ Field *example= ((Item_type_holder *)item)->example();
+ if (example)
+ return create_tmp_field_from_field(thd, example, item, table, 0);
+ return create_tmp_field_from_item(thd, item, table, copy_func, 0);
}
default: // Dosen't have to be stored
return 0;
@@ -9077,7 +9149,7 @@ int mysql_explain_select(THD *thd, SELECT_LEX *select_lex, char const *type,
select_lex->having,
(ORDER*) thd->lex.proc_list.first,
select_lex->options | thd->options | SELECT_DESCRIBE,
- result, unit, select_lex, 0);
+ result, unit, select_lex);
DBUG_RETURN(res);
}
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 5f0370a5a32..2e101c78613 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -266,7 +266,7 @@ class JOIN :public Sql_alloc
int prepare(Item ***rref_pointer_array, TABLE_LIST *tables, uint wind_num,
COND *conds, uint og_num, ORDER *order, ORDER *group,
Item *having, ORDER *proc_param, SELECT_LEX *select,
- SELECT_LEX_UNIT *unit, bool tables_and_fields_initied);
+ SELECT_LEX_UNIT *unit);
int optimize();
int reinit();
void exec();
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 5292299f928..e2c90e4ff4c 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,11 +106,11 @@ 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, select_result *sel_result)
{
SELECT_LEX *lex_select_save= thd->lex.current_select;
- SELECT_LEX *select_cursor,*sl;
+ SELECT_LEX *sl, *first_select;
+ select_result *tmp_result;
DBUG_ENTER("st_select_lex_unit::prepare");
/*
@@ -129,74 +123,33 @@ 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->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= tmp_table_param;
}
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);
+ tmp_result);
thd->lex.current_select= sl;
offset_limit_cnt= sl->offset_limit;
select_limit_cnt= sl->select_limit+sl->offset_limit;
@@ -215,27 +168,76 @@ 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;
+ sl, this);
if (res || thd->is_fatal_error)
goto err;
+ if (sl == first_select)
+ {
+ types.empty();
+ List_iterator_fast<Item> it(sl->item_list);
+ Item *item;
+ while((item= it++))
+ {
+ types.push_back(new Item_type_holder(thd, item));
+ }
+
+ if (thd->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;
+ while((type= tp++, item= it++))
+ {
+ ((Item_type_holder*)type)->join_types(thd, item);
+ }
+ }
}
- 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;
+ tmp_table_param.field_count= types.elements;
+ if (!(table= create_tmp_table(thd, &tmp_table_param, types,
+ (ORDER*) 0, !union_option, 1,
+ (first_select_in_union()->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;
+ union_result->set_table(table);
- for (field= table->field; *field; field++)
+ item_list.empty();
+ thd->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->lex.current_select= lex_select_save;
DBUG_RETURN(res || thd->is_fatal_error ? 1 : 0);
+
err:
thd->lex.current_select= lex_select_save;
DBUG_RETURN(-1);
@@ -419,7 +421,7 @@ int st_select_lex_unit::exec()
(ORDER*)global_parameters->order_list.first,
(ORDER*) NULL, NULL, (ORDER*) NULL,
options | SELECT_NO_UNLOCK,
- result, this, fake_select_lex, 0);
+ result, this, fake_select_lex);
if (!res)
thd->limit_found_rows = (ulonglong)table->file->records + add_rows;
/*
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 9214894e214..8b77f6958d0 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -461,7 +461,7 @@ int mysql_multi_update(THD *thd,
conds, 0, (ORDER *) NULL, (ORDER *)NULL, (Item *) NULL,
(ORDER *)NULL,
options | SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK,
- result, unit, select_lex, 0);
+ result, unit, select_lex);
delete result;
DBUG_RETURN(res);
}