mirror of
https://github.com/MariaDB/server.git
synced 2025-07-08 17:02:21 +03:00
Manual merge
This commit is contained in:
87
sql/item.h
87
sql/item.h
@ -126,8 +126,8 @@ public:
|
|||||||
top AND/OR ctructure of WHERE clause to protect it of
|
top AND/OR ctructure of WHERE clause to protect it of
|
||||||
optimisation changes in prepared statements
|
optimisation changes in prepared statements
|
||||||
*/
|
*/
|
||||||
Item(THD *thd, Item &item);
|
Item(THD *thd, Item *item);
|
||||||
virtual ~Item() { name=0; cleanup(); } /*lint -e1509 */
|
virtual ~Item() { name=0; } /*lint -e1509 */
|
||||||
void set_name(const char *str,uint length, CHARSET_INFO *cs);
|
void set_name(const char *str,uint length, CHARSET_INFO *cs);
|
||||||
void init_make_field(Send_field *tmp_field,enum enum_field_types type);
|
void init_make_field(Send_field *tmp_field,enum enum_field_types type);
|
||||||
virtual void cleanup() { fixed=0; }
|
virtual void cleanup() { fixed=0; }
|
||||||
@ -206,6 +206,7 @@ public:
|
|||||||
virtual Item *get_tmp_table_item(THD *thd) { return copy_or_same(thd); }
|
virtual Item *get_tmp_table_item(THD *thd) { return copy_or_same(thd); }
|
||||||
|
|
||||||
CHARSET_INFO *default_charset() const;
|
CHARSET_INFO *default_charset() const;
|
||||||
|
virtual CHARSET_INFO *compare_collation() { return NULL; }
|
||||||
|
|
||||||
virtual bool walk(Item_processor processor, byte *arg)
|
virtual bool walk(Item_processor processor, byte *arg)
|
||||||
{
|
{
|
||||||
@ -239,6 +240,11 @@ public:
|
|||||||
|
|
||||||
/* Used in sql_select.cc:eliminate_not_funcs() */
|
/* Used in sql_select.cc:eliminate_not_funcs() */
|
||||||
virtual Item *neg_transformer() { return NULL; }
|
virtual Item *neg_transformer() { return NULL; }
|
||||||
|
void delete_self()
|
||||||
|
{
|
||||||
|
cleanup();
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -304,7 +310,10 @@ public:
|
|||||||
|
|
||||||
inline void make_field(Send_field *field)
|
inline void make_field(Send_field *field)
|
||||||
{
|
{
|
||||||
this_item()->make_field(field);
|
Item *it= this_item();
|
||||||
|
|
||||||
|
it->set_name(m_name.str, m_name.length, system_charset_info);
|
||||||
|
it->make_field(field);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Item_result result_type() const
|
inline Item_result result_type() const
|
||||||
@ -326,6 +335,11 @@ public:
|
|||||||
{
|
{
|
||||||
str->append(m_name.str, m_name.length);
|
str->append(m_name.str, m_name.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool send(Protocol *protocol, String *str)
|
||||||
|
{
|
||||||
|
return this_item()->send(protocol, str);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -339,7 +353,7 @@ public:
|
|||||||
st_select_lex *depended_from;
|
st_select_lex *depended_from;
|
||||||
Item_ident(const char *db_name_par,const char *table_name_par,
|
Item_ident(const char *db_name_par,const char *table_name_par,
|
||||||
const char *field_name_par);
|
const char *field_name_par);
|
||||||
Item_ident(THD *thd, Item_ident &item);
|
Item_ident(THD *thd, Item_ident *item);
|
||||||
const char *full_name() const;
|
const char *full_name() const;
|
||||||
|
|
||||||
bool remove_dependence_processor(byte * arg);
|
bool remove_dependence_processor(byte * arg);
|
||||||
@ -362,7 +376,7 @@ public:
|
|||||||
item_equal(0)
|
item_equal(0)
|
||||||
{ collation.set(DERIVATION_IMPLICIT); }
|
{ collation.set(DERIVATION_IMPLICIT); }
|
||||||
// Constructor need to process subselect with temporary tables (see Item)
|
// Constructor need to process subselect with temporary tables (see Item)
|
||||||
Item_field(THD *thd, Item_field &item);
|
Item_field(THD *thd, Item_field *item);
|
||||||
Item_field(Field *field);
|
Item_field(Field *field);
|
||||||
enum Type type() const { return FIELD_ITEM; }
|
enum Type type() const { return FIELD_ITEM; }
|
||||||
bool eq(const Item *item, bool binary_cmp) const;
|
bool eq(const Item *item, bool binary_cmp) const;
|
||||||
@ -393,6 +407,7 @@ public:
|
|||||||
bool get_time(TIME *ltime);
|
bool get_time(TIME *ltime);
|
||||||
bool is_null() { return field->is_null(); }
|
bool is_null() { return field->is_null(); }
|
||||||
Item *get_tmp_table_item(THD *thd);
|
Item *get_tmp_table_item(THD *thd);
|
||||||
|
void cleanup();
|
||||||
Item_equal *find_item_equal(COND_EQUAL *cond_equal);
|
Item_equal *find_item_equal(COND_EQUAL *cond_equal);
|
||||||
Item *equal_fields_propagator(byte *arg);
|
Item *equal_fields_propagator(byte *arg);
|
||||||
bool replace_equal_field_processor(byte *arg);
|
bool replace_equal_field_processor(byte *arg);
|
||||||
@ -583,7 +598,7 @@ public:
|
|||||||
CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE)
|
CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE)
|
||||||
{
|
{
|
||||||
collation.set(cs, dv);
|
collation.set(cs, dv);
|
||||||
str_value.set(str,length,cs);
|
str_value.set_or_copy_aligned(str,length,cs);
|
||||||
/*
|
/*
|
||||||
We have to have a different max_length than 'length' here to
|
We have to have a different max_length than 'length' here to
|
||||||
ensure that we get the right length if we do use the item
|
ensure that we get the right length if we do use the item
|
||||||
@ -599,12 +614,11 @@ public:
|
|||||||
CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE)
|
CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE)
|
||||||
{
|
{
|
||||||
collation.set(cs, dv);
|
collation.set(cs, dv);
|
||||||
str_value.set(str,length,cs);
|
str_value.set_or_copy_aligned(str,length,cs);
|
||||||
max_length= str_value.numchars()*cs->mbmaxlen;
|
max_length= str_value.numchars()*cs->mbmaxlen;
|
||||||
set_name(name_par,0,cs);
|
set_name(name_par,0,cs);
|
||||||
decimals=NOT_FIXED_DEC;
|
decimals=NOT_FIXED_DEC;
|
||||||
}
|
}
|
||||||
~Item_string() {}
|
|
||||||
enum Type type() const { return STRING_ITEM; }
|
enum Type type() const { return STRING_ITEM; }
|
||||||
double val()
|
double val()
|
||||||
{
|
{
|
||||||
@ -671,7 +685,6 @@ class Item_varbinary :public Item
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Item_varbinary(const char *str,uint str_length);
|
Item_varbinary(const char *str,uint str_length);
|
||||||
~Item_varbinary() {}
|
|
||||||
enum Type type() const { return VARBIN_ITEM; }
|
enum Type type() const { return VARBIN_ITEM; }
|
||||||
double val() { return (double) Item_varbinary::val_int(); }
|
double val() { return (double) Item_varbinary::val_int(); }
|
||||||
longlong val_int();
|
longlong val_int();
|
||||||
@ -688,8 +701,8 @@ public:
|
|||||||
Field *result_field; /* Save result here */
|
Field *result_field; /* Save result here */
|
||||||
Item_result_field() :result_field(0) {}
|
Item_result_field() :result_field(0) {}
|
||||||
// Constructor used for Item_sum/Item_cond_and/or (see Item comment)
|
// Constructor used for Item_sum/Item_cond_and/or (see Item comment)
|
||||||
Item_result_field(THD *thd, Item_result_field &item):
|
Item_result_field(THD *thd, Item_result_field *item):
|
||||||
Item(thd, item), result_field(item.result_field)
|
Item(thd, item), result_field(item->result_field)
|
||||||
{}
|
{}
|
||||||
~Item_result_field() {} /* Required with gcc 2.95 */
|
~Item_result_field() {} /* Required with gcc 2.95 */
|
||||||
Field *get_tmp_table_field() { return result_field; }
|
Field *get_tmp_table_field() { return result_field; }
|
||||||
@ -708,20 +721,25 @@ public:
|
|||||||
class Item_ref :public Item_ident
|
class Item_ref :public Item_ident
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Field *result_field; /* Save result here */
|
Field *result_field; /* Save result here */
|
||||||
Item **ref;
|
Item **ref;
|
||||||
Item_ref(const char *db_par, const char *table_name_par,
|
Item **hook_ptr; /* These two to restore */
|
||||||
const char *field_name_par)
|
Item *orig_item; /* things in 'cleanup()' */
|
||||||
:Item_ident(db_par,table_name_par,field_name_par),ref(0) {}
|
Item_ref(Item **hook, Item *original,const char *db_par,
|
||||||
Item_ref(Item **item, const char *table_name_par, const char *field_name_par)
|
const char *table_name_par, const char *field_name_par)
|
||||||
:Item_ident(NullS,table_name_par,field_name_par),ref(item) {}
|
:Item_ident(db_par,table_name_par,field_name_par),ref(0), hook_ptr(hook),
|
||||||
|
orig_item(original) {}
|
||||||
|
Item_ref(Item **item, Item **hook,
|
||||||
|
const char *table_name_par, const char *field_name_par)
|
||||||
|
:Item_ident(NullS,table_name_par,field_name_par),
|
||||||
|
ref(item), hook_ptr(hook), orig_item(hook ? *hook:0) {}
|
||||||
// Constructor need to process subselect with temporary tables (see Item)
|
// Constructor need to process subselect with temporary tables (see Item)
|
||||||
Item_ref(THD *thd, Item_ref &item)
|
Item_ref(THD *thd, Item_ref *item, Item **hook)
|
||||||
:Item_ident(thd, item), ref(item.ref) {}
|
:Item_ident(thd, item), ref(item->ref),
|
||||||
|
hook_ptr(hook), orig_item(hook ? *hook : 0) {}
|
||||||
enum Type type() const { return REF_ITEM; }
|
enum Type type() const { return REF_ITEM; }
|
||||||
bool eq(const Item *item, bool binary_cmp) const
|
bool eq(const Item *item, bool binary_cmp) const
|
||||||
{ return ref && (*ref)->eq(item, binary_cmp); }
|
{ return ref && (*ref)->eq(item, binary_cmp); }
|
||||||
~Item_ref() { if (ref && (*ref) && (*ref) != this) delete *ref; }
|
|
||||||
double val()
|
double val()
|
||||||
{
|
{
|
||||||
double tmp=(*ref)->val_result();
|
double tmp=(*ref)->val_result();
|
||||||
@ -766,6 +784,7 @@ public:
|
|||||||
}
|
}
|
||||||
Item *real_item() { return *ref; }
|
Item *real_item() { return *ref; }
|
||||||
void print(String *str);
|
void print(String *str);
|
||||||
|
void cleanup();
|
||||||
};
|
};
|
||||||
|
|
||||||
class Item_in_subselect;
|
class Item_in_subselect;
|
||||||
@ -776,7 +795,7 @@ protected:
|
|||||||
public:
|
public:
|
||||||
Item_ref_null_helper(Item_in_subselect* master, Item **item,
|
Item_ref_null_helper(Item_in_subselect* master, Item **item,
|
||||||
const char *table_name_par, const char *field_name_par):
|
const char *table_name_par, const char *field_name_par):
|
||||||
Item_ref(item, table_name_par, field_name_par), owner(master) {}
|
Item_ref(item, NULL, table_name_par, field_name_par), owner(master) {}
|
||||||
double val();
|
double val();
|
||||||
longlong val_int();
|
longlong val_int();
|
||||||
String* val_str(String* s);
|
String* val_str(String* s);
|
||||||
@ -840,7 +859,6 @@ public:
|
|||||||
name=item->name;
|
name=item->name;
|
||||||
cached_field_type= item->field_type();
|
cached_field_type= item->field_type();
|
||||||
}
|
}
|
||||||
~Item_copy_string() { delete item; }
|
|
||||||
enum Type type() const { return COPY_STR_ITEM; }
|
enum Type type() const { return COPY_STR_ITEM; }
|
||||||
enum Item_result result_type () const { return STRING_RESULT; }
|
enum Item_result result_type () const { return STRING_RESULT; }
|
||||||
enum_field_types field_type() const { return cached_field_type; }
|
enum_field_types field_type() const { return cached_field_type; }
|
||||||
@ -997,13 +1015,15 @@ public:
|
|||||||
void set_used_tables(table_map map) { used_table_map= map; }
|
void set_used_tables(table_map map) { used_table_map= map; }
|
||||||
|
|
||||||
virtual bool allocate(uint i) { return 0; };
|
virtual bool allocate(uint i) { return 0; };
|
||||||
virtual bool setup(Item *item) { example= item; return 0; };
|
virtual bool setup(Item *item)
|
||||||
virtual void store(Item *)= 0;
|
|
||||||
void set_len_n_dec(uint32 max_len, uint8 dec)
|
|
||||||
{
|
{
|
||||||
max_length= max_len;
|
example= item;
|
||||||
decimals= dec;
|
max_length= item->max_length;
|
||||||
}
|
decimals= item->decimals;
|
||||||
|
collation.set(item->collation);
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
virtual void store(Item *)= 0;
|
||||||
enum Type type() const { return CACHE_ITEM; }
|
enum Type type() const { return CACHE_ITEM; }
|
||||||
static Item_cache* get_cache(Item_result type);
|
static Item_cache* get_cache(Item_result type);
|
||||||
table_map used_tables() const { return used_table_map; }
|
table_map used_tables() const { return used_table_map; }
|
||||||
@ -1101,6 +1121,11 @@ public:
|
|||||||
bool check_cols(uint c);
|
bool check_cols(uint c);
|
||||||
bool null_inside();
|
bool null_inside();
|
||||||
void bring_value();
|
void bring_value();
|
||||||
|
void cleanup()
|
||||||
|
{
|
||||||
|
Item_cache::cleanup();
|
||||||
|
values= 0;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -1111,6 +1136,7 @@ class Item_type_holder: public Item
|
|||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
Item_result item_type;
|
Item_result item_type;
|
||||||
|
Item_result orig_type;
|
||||||
Field *field_example;
|
Field *field_example;
|
||||||
public:
|
public:
|
||||||
Item_type_holder(THD*, Item*);
|
Item_type_holder(THD*, Item*);
|
||||||
@ -1122,6 +1148,11 @@ public:
|
|||||||
String *val_str(String*);
|
String *val_str(String*);
|
||||||
bool join_types(THD *thd, Item *);
|
bool join_types(THD *thd, Item *);
|
||||||
Field *example() { return field_example; }
|
Field *example() { return field_example; }
|
||||||
|
void cleanup()
|
||||||
|
{
|
||||||
|
Item::cleanup();
|
||||||
|
item_type= orig_type;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
102
sql/opt_range.cc
102
sql/opt_range.cc
@ -301,10 +301,11 @@ typedef struct st_qsel_param {
|
|||||||
uint imerge_cost_buff_size; /* size of the buffer */
|
uint imerge_cost_buff_size; /* size of the buffer */
|
||||||
} PARAM;
|
} PARAM;
|
||||||
|
|
||||||
static SEL_TREE * get_mm_parts(PARAM *param,Field *field,
|
static SEL_TREE * get_mm_parts(PARAM *param,COND *cond_func,Field *field,
|
||||||
Item_func::Functype type,Item *value,
|
Item_func::Functype type,Item *value,
|
||||||
Item_result cmp_type);
|
Item_result cmp_type);
|
||||||
static SEL_ARG *get_mm_leaf(PARAM *param,Field *field,KEY_PART *key_part,
|
static SEL_ARG *get_mm_leaf(PARAM *param,COND *cond_func,Field *field,
|
||||||
|
KEY_PART *key_part,
|
||||||
Item_func::Functype type,Item *value);
|
Item_func::Functype type,Item *value);
|
||||||
static SEL_TREE *get_mm_tree(PARAM *param,COND *cond);
|
static SEL_TREE *get_mm_tree(PARAM *param,COND *cond);
|
||||||
static ha_rows check_quick_select(PARAM *param,uint index,SEL_ARG *key_tree);
|
static ha_rows check_quick_select(PARAM *param,uint index,SEL_ARG *key_tree);
|
||||||
@ -612,14 +613,25 @@ SQL_SELECT::SQL_SELECT() :quick(0),cond(0),free_cond(0)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SQL_SELECT::~SQL_SELECT()
|
void SQL_SELECT::cleanup()
|
||||||
{
|
{
|
||||||
delete quick;
|
delete quick;
|
||||||
|
quick= 0;
|
||||||
if (free_cond)
|
if (free_cond)
|
||||||
|
{
|
||||||
|
free_cond=0;
|
||||||
delete cond;
|
delete cond;
|
||||||
|
cond= 0;
|
||||||
|
}
|
||||||
close_cached_file(&file);
|
close_cached_file(&file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SQL_SELECT::~SQL_SELECT()
|
||||||
|
{
|
||||||
|
cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
#undef index // Fix for Unixware 7
|
#undef index // Fix for Unixware 7
|
||||||
|
|
||||||
QUICK_SELECT_I::QUICK_SELECT_I()
|
QUICK_SELECT_I::QUICK_SELECT_I()
|
||||||
@ -1746,7 +1758,8 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
|
|||||||
|
|
||||||
|
|
||||||
static SEL_TREE *
|
static SEL_TREE *
|
||||||
get_mm_parts(PARAM *param, Field *field, Item_func::Functype type,
|
get_mm_parts(PARAM *param, COND *cond_func, Field *field,
|
||||||
|
Item_func::Functype type,
|
||||||
Item *value, Item_result cmp_type)
|
Item *value, Item_result cmp_type)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("get_mm_parts");
|
DBUG_ENTER("get_mm_parts");
|
||||||
@ -1768,7 +1781,8 @@ get_mm_parts(PARAM *param, Field *field, Item_func::Functype type,
|
|||||||
DBUG_RETURN(0); // OOM
|
DBUG_RETURN(0); // OOM
|
||||||
if (!value || !(value->used_tables() & ~param->read_tables))
|
if (!value || !(value->used_tables() & ~param->read_tables))
|
||||||
{
|
{
|
||||||
sel_arg=get_mm_leaf(param,key_part->field,key_part,type,value);
|
sel_arg=get_mm_leaf(param,cond_func,
|
||||||
|
key_part->field,key_part,type,value);
|
||||||
if (!sel_arg)
|
if (!sel_arg)
|
||||||
continue;
|
continue;
|
||||||
if (sel_arg->type == SEL_ARG::IMPOSSIBLE)
|
if (sel_arg->type == SEL_ARG::IMPOSSIBLE)
|
||||||
@ -1794,7 +1808,7 @@ get_mm_parts(PARAM *param, Field *field, Item_func::Functype type,
|
|||||||
|
|
||||||
|
|
||||||
static SEL_ARG *
|
static SEL_ARG *
|
||||||
get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part,
|
get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
|
||||||
Item_func::Functype type,Item *value)
|
Item_func::Functype type,Item *value)
|
||||||
{
|
{
|
||||||
uint maybe_null=(uint) field->real_maybe_null(), copies;
|
uint maybe_null=(uint) field->real_maybe_null(), copies;
|
||||||
@ -1803,6 +1817,32 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part,
|
|||||||
char *str, *str2;
|
char *str, *str2;
|
||||||
DBUG_ENTER("get_mm_leaf");
|
DBUG_ENTER("get_mm_leaf");
|
||||||
|
|
||||||
|
if (!value) // IS NULL or IS NOT NULL
|
||||||
|
{
|
||||||
|
if (field->table->outer_join) // Can't use a key on this
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
if (!maybe_null) // Not null field
|
||||||
|
DBUG_RETURN(type == Item_func::ISNULL_FUNC ? &null_element : 0);
|
||||||
|
if (!(tree=new SEL_ARG(field,is_null_string,is_null_string)))
|
||||||
|
DBUG_RETURN(0); // out of memory
|
||||||
|
if (type == Item_func::ISNOTNULL_FUNC)
|
||||||
|
{
|
||||||
|
tree->min_flag=NEAR_MIN; /* IS NOT NULL -> X > NULL */
|
||||||
|
tree->max_flag=NO_MAX_RANGE;
|
||||||
|
}
|
||||||
|
DBUG_RETURN(tree);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
We can't use an index when comparing strings of
|
||||||
|
different collations
|
||||||
|
*/
|
||||||
|
if (field->result_type() == STRING_RESULT &&
|
||||||
|
value->result_type() == STRING_RESULT &&
|
||||||
|
key_part->image_type == Field::itRAW &&
|
||||||
|
((Field_str*)field)->charset() != conf_func->compare_collation())
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
|
||||||
if (type == Item_func::LIKE_FUNC)
|
if (type == Item_func::LIKE_FUNC)
|
||||||
{
|
{
|
||||||
bool like_error;
|
bool like_error;
|
||||||
@ -1866,22 +1906,6 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part,
|
|||||||
DBUG_RETURN(new SEL_ARG(field,min_str,max_str));
|
DBUG_RETURN(new SEL_ARG(field,min_str,max_str));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!value) // IS NULL or IS NOT NULL
|
|
||||||
{
|
|
||||||
if (field->table->outer_join) // Can't use a key on this
|
|
||||||
DBUG_RETURN(0);
|
|
||||||
if (!maybe_null) // Not null field
|
|
||||||
DBUG_RETURN(type == Item_func::ISNULL_FUNC ? &null_element : 0);
|
|
||||||
if (!(tree=new SEL_ARG(field,is_null_string,is_null_string)))
|
|
||||||
DBUG_RETURN(0); // out of memory
|
|
||||||
if (type == Item_func::ISNOTNULL_FUNC)
|
|
||||||
{
|
|
||||||
tree->min_flag=NEAR_MIN; /* IS NOT NULL -> X > NULL */
|
|
||||||
tree->max_flag=NO_MAX_RANGE;
|
|
||||||
}
|
|
||||||
DBUG_RETURN(tree);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!field->optimize_range(param->real_keynr[key_part->key]) &&
|
if (!field->optimize_range(param->real_keynr[key_part->key]) &&
|
||||||
type != Item_func::EQ_FUNC &&
|
type != Item_func::EQ_FUNC &&
|
||||||
type != Item_func::EQUAL_FUNC)
|
type != Item_func::EQUAL_FUNC)
|
||||||
@ -3097,6 +3121,7 @@ check_quick_select(PARAM *param,uint idx,SEL_ARG *tree)
|
|||||||
param->table->quick_rows[key]=records;
|
param->table->quick_rows[key]=records;
|
||||||
param->table->quick_key_parts[key]=param->max_key_part+1;
|
param->table->quick_key_parts[key]=param->max_key_part+1;
|
||||||
}
|
}
|
||||||
|
DBUG_PRINT("exit", ("Records: %lu", (ulong) records));
|
||||||
DBUG_RETURN(records);
|
DBUG_RETURN(records);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3440,8 +3465,30 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
|
|||||||
key_part->part_length+=HA_KEY_BLOB_LENGTH;
|
key_part->part_length+=HA_KEY_BLOB_LENGTH;
|
||||||
key_part->null_bit= key_info->key_part[part].null_bit;
|
key_part->null_bit= key_info->key_part[part].null_bit;
|
||||||
}
|
}
|
||||||
if (!insert_dynamic(&quick->ranges,(gptr)&range))
|
if (insert_dynamic(&quick->ranges,(gptr)&range))
|
||||||
return quick;
|
goto err;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add a NULL range if REF_OR_NULL optimization is used.
|
||||||
|
For example:
|
||||||
|
if we have "WHERE A=2 OR A IS NULL" we created the (A=2) range above
|
||||||
|
and have ref->null_ref_key set. Will create a new NULL range here.
|
||||||
|
*/
|
||||||
|
if (ref->null_ref_key)
|
||||||
|
{
|
||||||
|
QUICK_RANGE *null_range;
|
||||||
|
|
||||||
|
*ref->null_ref_key= 1; // Set null byte then create a range
|
||||||
|
if (!(null_range= new QUICK_RANGE(ref->key_buff, ref->key_length,
|
||||||
|
ref->key_buff, ref->key_length,
|
||||||
|
EQ_RANGE)))
|
||||||
|
goto err;
|
||||||
|
*ref->null_ref_key= 0; // Clear null byte
|
||||||
|
if (insert_dynamic(&quick->ranges,(gptr)&null_range))
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return quick;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
delete quick;
|
delete quick;
|
||||||
@ -3584,12 +3631,7 @@ int QUICK_RANGE_SELECT::get_next()
|
|||||||
int result;
|
int result;
|
||||||
if (range)
|
if (range)
|
||||||
{ // Already read through key
|
{ // Already read through key
|
||||||
/* result=((range->flag & EQ_RANGE) ?
|
result=((range->flag & (EQ_RANGE | GEOM_FLAG)) ?
|
||||||
file->index_next_same(record, (byte*) range->min_key,
|
|
||||||
range->min_length) :
|
|
||||||
file->index_next(record));
|
|
||||||
*/
|
|
||||||
result=((range->flag & (EQ_RANGE | GEOM_FLAG) ) ?
|
|
||||||
file->index_next_same(record, (byte*) range->min_key,
|
file->index_next_same(record, (byte*) range->min_key,
|
||||||
range->min_length) :
|
range->min_length) :
|
||||||
file->index_next(record));
|
file->index_next(record));
|
||||||
|
@ -24,8 +24,6 @@
|
|||||||
#include "mysql_priv.h"
|
#include "mysql_priv.h"
|
||||||
#include "sql_select.h"
|
#include "sql_select.h"
|
||||||
|
|
||||||
#include "opt_ft.h"
|
|
||||||
|
|
||||||
#include <m_ctype.h>
|
#include <m_ctype.h>
|
||||||
#include <hash.h>
|
#include <hash.h>
|
||||||
#include <ft_global.h>
|
#include <ft_global.h>
|
||||||
@ -89,7 +87,7 @@ static int do_select(JOIN *join,List<Item> *fields,TABLE *tmp_table,
|
|||||||
Procedure *proc);
|
Procedure *proc);
|
||||||
static int sub_select_cache(JOIN *join,JOIN_TAB *join_tab,bool end_of_records);
|
static int sub_select_cache(JOIN *join,JOIN_TAB *join_tab,bool end_of_records);
|
||||||
static int sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records);
|
static int sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records);
|
||||||
static int flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skipp_last);
|
static int flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skip_last);
|
||||||
static int end_send(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
|
static int end_send(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
|
||||||
static int end_send_group(JOIN *join, JOIN_TAB *join_tab,bool end_of_records);
|
static int end_send_group(JOIN *join, JOIN_TAB *join_tab,bool end_of_records);
|
||||||
static int end_write(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
|
static int end_write(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
|
||||||
@ -182,7 +180,6 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
|
|||||||
register SELECT_LEX *select_lex = &lex->select_lex;
|
register SELECT_LEX *select_lex = &lex->select_lex;
|
||||||
DBUG_ENTER("handle_select");
|
DBUG_ENTER("handle_select");
|
||||||
|
|
||||||
fix_tables_pointers(lex->all_selects_list);
|
|
||||||
if (select_lex->next_select())
|
if (select_lex->next_select())
|
||||||
res=mysql_union(thd, lex, result, &lex->unit);
|
res=mysql_union(thd, lex, result, &lex->unit);
|
||||||
else
|
else
|
||||||
@ -309,7 +306,7 @@ JOIN::prepare(Item ***rref_pointer_array,
|
|||||||
|
|
||||||
/* Check that all tables, fields, conds and order are ok */
|
/* Check that all tables, fields, conds and order are ok */
|
||||||
|
|
||||||
if (setup_tables(tables_list) ||
|
if (setup_tables(tables_list, 0) ||
|
||||||
setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) ||
|
setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) ||
|
||||||
select_lex->setup_ref_array(thd, og_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), tables_list, fields_list, 1,
|
||||||
@ -939,8 +936,10 @@ JOIN::optimize()
|
|||||||
as in other cases the join is done before the sort.
|
as in other cases the join is done before the sort.
|
||||||
*/
|
*/
|
||||||
if (const_tables != tables &&
|
if (const_tables != tables &&
|
||||||
(order || group_list) && join_tab[const_tables].type != JT_ALL &&
|
(order || group_list) &&
|
||||||
|
join_tab[const_tables].type != JT_ALL &&
|
||||||
join_tab[const_tables].type != JT_FT &&
|
join_tab[const_tables].type != JT_FT &&
|
||||||
|
join_tab[const_tables].type != JT_REF_OR_NULL &&
|
||||||
(order && simple_order || group_list && simple_group))
|
(order && simple_order || group_list && simple_group))
|
||||||
{
|
{
|
||||||
if (add_ref_to_table_cond(thd,&join_tab[const_tables]))
|
if (add_ref_to_table_cond(thd,&join_tab[const_tables]))
|
||||||
@ -1094,7 +1093,7 @@ JOIN::reinit()
|
|||||||
if (unit->select_limit_cnt == HA_POS_ERROR)
|
if (unit->select_limit_cnt == HA_POS_ERROR)
|
||||||
select_lex->options&= ~OPTION_FOUND_ROWS;
|
select_lex->options&= ~OPTION_FOUND_ROWS;
|
||||||
|
|
||||||
if (setup_tables(tables_list))
|
if (setup_tables(tables_list, 1))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
|
|
||||||
/* Reset of sum functions */
|
/* Reset of sum functions */
|
||||||
@ -1590,12 +1589,7 @@ JOIN::cleanup()
|
|||||||
JOIN_TAB *tab, *end;
|
JOIN_TAB *tab, *end;
|
||||||
for (tab= join_tab, end= tab+tables ; tab != end ; tab++)
|
for (tab= join_tab, end= tab+tables ; tab != end ; tab++)
|
||||||
{
|
{
|
||||||
delete tab->select;
|
tab->cleanup();
|
||||||
delete tab->quick;
|
|
||||||
tab->select=0;
|
|
||||||
tab->quick=0;
|
|
||||||
x_free(tab->cache.buff);
|
|
||||||
tab->cache.buff= 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tmp_join->tmp_join= 0;
|
tmp_join->tmp_join= 0;
|
||||||
@ -1659,13 +1653,14 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free_join= 0;
|
|
||||||
}
|
}
|
||||||
|
free_join= 0;
|
||||||
join->select_options= select_options;
|
join->select_options= select_options;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
join= new JOIN(thd, fields, select_options, result);
|
if (!(join= new JOIN(thd, fields, select_options, result)))
|
||||||
|
DBUG_RETURN(-1);
|
||||||
thd->proc_info="init";
|
thd->proc_info="init";
|
||||||
thd->used_tables=0; // Updated by setup_fields
|
thd->used_tables=0; // Updated by setup_fields
|
||||||
if (join->prepare(rref_pointer_array, tables, wild_num,
|
if (join->prepare(rref_pointer_array, tables, wild_num,
|
||||||
@ -1726,8 +1721,8 @@ static ha_rows get_quick_record_count(THD *thd, SQL_SELECT *select,
|
|||||||
{
|
{
|
||||||
select->head=table;
|
select->head=table;
|
||||||
table->reginfo.impossible_range=0;
|
table->reginfo.impossible_range=0;
|
||||||
if ((error=select->test_quick_select(thd, *(key_map *)keys,(table_map) 0,limit))
|
if ((error=select->test_quick_select(thd, *(key_map *)keys,(table_map) 0,
|
||||||
== 1)
|
limit)) == 1)
|
||||||
DBUG_RETURN(select->quick->records);
|
DBUG_RETURN(select->quick->records);
|
||||||
if (error == -1)
|
if (error == -1)
|
||||||
{
|
{
|
||||||
@ -2210,7 +2205,7 @@ merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_key_field(KEY_FIELD **key_fields,uint and_level,
|
add_key_field(KEY_FIELD **key_fields,uint and_level, COND *cond,
|
||||||
Field *field,bool eq_func,Item **value, uint num_values,
|
Field *field,bool eq_func,Item **value, uint num_values,
|
||||||
table_map usable_tables)
|
table_map usable_tables)
|
||||||
{
|
{
|
||||||
@ -2277,6 +2272,17 @@ add_key_field(KEY_FIELD **key_fields,uint and_level,
|
|||||||
(*value)->result_type() != STRING_RESULT &&
|
(*value)->result_type() != STRING_RESULT &&
|
||||||
field->cmp_type() != (*value)->result_type())
|
field->cmp_type() != (*value)->result_type())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
We can't use indexes if the effective collation
|
||||||
|
of the operation differ from the field collation.
|
||||||
|
*/
|
||||||
|
if (field->result_type() == STRING_RESULT &&
|
||||||
|
(*value)->result_type() == STRING_RESULT &&
|
||||||
|
field->cmp_type() == STRING_RESULT &&
|
||||||
|
((Field_str*)field)->charset() != cond->compare_collation())
|
||||||
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DBUG_ASSERT(num_values == 1);
|
DBUG_ASSERT(num_values == 1);
|
||||||
@ -3441,7 +3447,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
|
|||||||
{
|
{
|
||||||
/* Must read with repeat */
|
/* Must read with repeat */
|
||||||
j->type= null_ref_key ? JT_REF_OR_NULL : JT_REF;
|
j->type= null_ref_key ? JT_REF_OR_NULL : JT_REF;
|
||||||
j->null_ref_key= null_ref_key;
|
j->ref.null_ref_key= null_ref_key;
|
||||||
}
|
}
|
||||||
else if (ref_key == j->ref.key_copy)
|
else if (ref_key == j->ref.key_copy)
|
||||||
{
|
{
|
||||||
@ -3920,6 +3926,41 @@ bool error_if_full_join(JOIN *join)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
cleanup JOIN_TAB
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
JOIN_TAB::cleanup()
|
||||||
|
*/
|
||||||
|
|
||||||
|
void JOIN_TAB::cleanup()
|
||||||
|
{
|
||||||
|
delete select;
|
||||||
|
select= 0;
|
||||||
|
delete quick;
|
||||||
|
quick= 0;
|
||||||
|
x_free(cache.buff);
|
||||||
|
cache.buff= 0;
|
||||||
|
if (table)
|
||||||
|
{
|
||||||
|
if (table->key_read)
|
||||||
|
{
|
||||||
|
table->key_read= 0;
|
||||||
|
table->file->extra(HA_EXTRA_NO_KEYREAD);
|
||||||
|
}
|
||||||
|
/* Don't free index if we are using read_record */
|
||||||
|
if (!read_record.table)
|
||||||
|
table->file->index_end();
|
||||||
|
/*
|
||||||
|
We need to reset this for next select
|
||||||
|
(Tested in part_of_refkey)
|
||||||
|
*/
|
||||||
|
table->reginfo.join_tab= 0;
|
||||||
|
}
|
||||||
|
end_read_record(&read_record);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Free resources of given join
|
Free resources of given join
|
||||||
|
|
||||||
@ -3954,11 +3995,6 @@ JOIN::join_free(bool full)
|
|||||||
{
|
{
|
||||||
if (tab->table)
|
if (tab->table)
|
||||||
{
|
{
|
||||||
if (tab->table->key_read)
|
|
||||||
{
|
|
||||||
tab->table->key_read= 0;
|
|
||||||
tab->table->file->extra(HA_EXTRA_NO_KEYREAD);
|
|
||||||
}
|
|
||||||
/* Don't free index if we are using read_record */
|
/* Don't free index if we are using read_record */
|
||||||
if (!tab->read_record.table)
|
if (!tab->read_record.table)
|
||||||
tab->table->file->index_end();
|
tab->table->file->index_end();
|
||||||
@ -3969,29 +4005,7 @@ JOIN::join_free(bool full)
|
|||||||
{
|
{
|
||||||
for (tab= join_tab, end= tab+tables; tab != end; tab++)
|
for (tab= join_tab, end= tab+tables; tab != end; tab++)
|
||||||
{
|
{
|
||||||
delete tab->select;
|
tab->cleanup();
|
||||||
delete tab->quick;
|
|
||||||
tab->select=0;
|
|
||||||
tab->quick=0;
|
|
||||||
x_free(tab->cache.buff);
|
|
||||||
tab->cache.buff= 0;
|
|
||||||
if (tab->table)
|
|
||||||
{
|
|
||||||
if (tab->table->key_read)
|
|
||||||
{
|
|
||||||
tab->table->key_read= 0;
|
|
||||||
tab->table->file->extra(HA_EXTRA_NO_KEYREAD);
|
|
||||||
}
|
|
||||||
/* Don't free index if we are using read_record */
|
|
||||||
if (!tab->read_record.table)
|
|
||||||
tab->table->file->index_end();
|
|
||||||
/*
|
|
||||||
We need to reset this for next select
|
|
||||||
(Tested in part_of_refkey)
|
|
||||||
*/
|
|
||||||
tab->table->reginfo.join_tab= 0;
|
|
||||||
}
|
|
||||||
end_read_record(&tab->read_record);
|
|
||||||
}
|
}
|
||||||
table= 0;
|
table= 0;
|
||||||
}
|
}
|
||||||
@ -5237,17 +5251,9 @@ remove_eq_conds(COND *cond,Item::cond_result *cond_value)
|
|||||||
{
|
{
|
||||||
Item *new_item=remove_eq_conds(item,&tmp_cond_value);
|
Item *new_item=remove_eq_conds(item,&tmp_cond_value);
|
||||||
if (!new_item)
|
if (!new_item)
|
||||||
{
|
|
||||||
#ifdef DELETE_ITEMS
|
|
||||||
delete item; // This may be shared
|
|
||||||
#endif
|
|
||||||
li.remove();
|
li.remove();
|
||||||
}
|
|
||||||
else if (item != new_item)
|
else if (item != new_item)
|
||||||
{
|
{
|
||||||
#ifdef DELETE_ITEMS
|
|
||||||
delete item; // This may be shared
|
|
||||||
#endif
|
|
||||||
VOID(li.replace(new_item));
|
VOID(li.replace(new_item));
|
||||||
should_fix_fields=1;
|
should_fix_fields=1;
|
||||||
}
|
}
|
||||||
@ -6604,14 +6610,14 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
|
|||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skipp_last)
|
flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skip_last)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
READ_RECORD *info;
|
READ_RECORD *info;
|
||||||
|
|
||||||
if (!join_tab->cache.records)
|
if (!join_tab->cache.records)
|
||||||
return 0; /* Nothing to do */
|
return 0; /* Nothing to do */
|
||||||
if (skipp_last)
|
if (skip_last)
|
||||||
(void) store_record_in_cache(&join_tab->cache); // Must save this for later
|
(void) store_record_in_cache(&join_tab->cache); // Must save this for later
|
||||||
if (join_tab->use_quick == 2)
|
if (join_tab->use_quick == 2)
|
||||||
{
|
{
|
||||||
@ -6645,21 +6651,21 @@ flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skipp_last)
|
|||||||
}
|
}
|
||||||
SQL_SELECT *select=join_tab->select;
|
SQL_SELECT *select=join_tab->select;
|
||||||
if (!error && (!join_tab->cache.select ||
|
if (!error && (!join_tab->cache.select ||
|
||||||
!join_tab->cache.select->skipp_record()))
|
!join_tab->cache.select->skip_record()))
|
||||||
{
|
{
|
||||||
uint i;
|
uint i;
|
||||||
reset_cache(&join_tab->cache);
|
reset_cache(&join_tab->cache);
|
||||||
for (i=(join_tab->cache.records- (skipp_last ? 1 : 0)) ; i-- > 0 ;)
|
for (i=(join_tab->cache.records- (skip_last ? 1 : 0)) ; i-- > 0 ;)
|
||||||
{
|
{
|
||||||
read_cached_record(join_tab);
|
read_cached_record(join_tab);
|
||||||
if (!select || !select->skipp_record())
|
if (!select || !select->skip_record())
|
||||||
if ((error=(join_tab->next_select)(join,join_tab+1,0)) < 0)
|
if ((error=(join_tab->next_select)(join,join_tab+1,0)) < 0)
|
||||||
return error; /* purecov: inspected */
|
return error; /* purecov: inspected */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (!(error=info->read_record(info)));
|
} while (!(error=info->read_record(info)));
|
||||||
|
|
||||||
if (skipp_last)
|
if (skip_last)
|
||||||
read_cached_record(join_tab); // Restore current record
|
read_cached_record(join_tab); // Restore current record
|
||||||
reset_cache(&join_tab->cache);
|
reset_cache(&join_tab->cache);
|
||||||
join_tab->cache.records=0; join_tab->cache.ptr_record= (uint) ~0;
|
join_tab->cache.records=0; join_tab->cache.ptr_record= (uint) ~0;
|
||||||
@ -7066,12 +7072,12 @@ join_read_always_key_or_null(JOIN_TAB *tab)
|
|||||||
int res;
|
int res;
|
||||||
|
|
||||||
/* First read according to key which is NOT NULL */
|
/* First read according to key which is NOT NULL */
|
||||||
*tab->null_ref_key=0;
|
*tab->ref.null_ref_key= 0; // Clear null byte
|
||||||
if ((res= join_read_always_key(tab)) >= 0)
|
if ((res= join_read_always_key(tab)) >= 0)
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
/* Then read key with null value */
|
/* Then read key with null value */
|
||||||
*tab->null_ref_key= 1;
|
*tab->ref.null_ref_key= 1; // Set null byte
|
||||||
return safe_index_read(tab);
|
return safe_index_read(tab);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7085,10 +7091,10 @@ join_read_next_same_or_null(READ_RECORD *info)
|
|||||||
JOIN_TAB *tab= info->table->reginfo.join_tab;
|
JOIN_TAB *tab= info->table->reginfo.join_tab;
|
||||||
|
|
||||||
/* Test if we have already done a read after null key */
|
/* Test if we have already done a read after null key */
|
||||||
if (*tab->null_ref_key)
|
if (*tab->ref.null_ref_key)
|
||||||
return -1; // All keys read
|
return -1; // All keys read
|
||||||
*tab->null_ref_key= 1; // Read null key
|
*tab->ref.null_ref_key= 1; // Set null byte
|
||||||
return safe_index_read(tab);
|
return safe_index_read(tab); // then read null keys
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -8061,8 +8067,9 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
|
|||||||
For impossible ranges (like when doing a lookup on NULL on a NOT NULL
|
For impossible ranges (like when doing a lookup on NULL on a NOT NULL
|
||||||
field, quick will contain an empty record set.
|
field, quick will contain an empty record set.
|
||||||
*/
|
*/
|
||||||
if (!(select->quick=get_ft_or_quick_select_for_ref(tab->join->thd,
|
if (!(select->quick= tab->type == JT_FT ?
|
||||||
table, tab)))
|
new FT_SELECT(thd, table, tab->ref.key) :
|
||||||
|
get_quick_select_for_ref(thd, table, &tab->ref)))
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -8070,9 +8077,12 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
|
|||||||
table->file->info(HA_STATUS_VARIABLE); // Get record count
|
table->file->info(HA_STATUS_VARIABLE); // Get record count
|
||||||
table->sort.found_records=filesort(thd, table,sortorder, length,
|
table->sort.found_records=filesort(thd, table,sortorder, length,
|
||||||
select, filesort_limit, &examined_rows);
|
select, filesort_limit, &examined_rows);
|
||||||
tab->records=table->sort.found_records; // For SQL_CALC_ROWS
|
tab->records= table->sort.found_records; // For SQL_CALC_ROWS
|
||||||
delete select; // filesort did select
|
if (select)
|
||||||
tab->select=0;
|
{
|
||||||
|
select->cleanup(); // filesort did select
|
||||||
|
tab->select= 0;
|
||||||
|
}
|
||||||
tab->select_cond=0;
|
tab->select_cond=0;
|
||||||
tab->type=JT_ALL; // Read with normal read_record
|
tab->type=JT_ALL; // Read with normal read_record
|
||||||
tab->read_first_record= join_init_read_record;
|
tab->read_first_record= join_init_read_record;
|
||||||
@ -9155,7 +9165,7 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
|
|||||||
if (pos->type() == Item::FIELD_ITEM)
|
if (pos->type() == Item::FIELD_ITEM)
|
||||||
{
|
{
|
||||||
Item_field *item;
|
Item_field *item;
|
||||||
if (!(item= new Item_field(thd, *((Item_field*) pos))))
|
if (!(item= new Item_field(thd, ((Item_field*) pos))))
|
||||||
goto err;
|
goto err;
|
||||||
pos= item;
|
pos= item;
|
||||||
if (item->field->flags & BLOB_FLAG)
|
if (item->field->flags & BLOB_FLAG)
|
||||||
@ -10056,20 +10066,23 @@ int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
|
|||||||
sl;
|
sl;
|
||||||
sl= sl->next_select())
|
sl= sl->next_select())
|
||||||
{
|
{
|
||||||
|
// drop UNCACHEABLE_EXPLAIN, because it is for internal usage only
|
||||||
|
uint8 uncacheable= (sl->uncacheable & ~UNCACHEABLE_EXPLAIN);
|
||||||
|
|
||||||
res= mysql_explain_select(thd, sl,
|
res= mysql_explain_select(thd, sl,
|
||||||
(((&thd->lex->select_lex)==sl)?
|
(((&thd->lex->select_lex)==sl)?
|
||||||
((thd->lex->all_selects_list != sl)?"PRIMARY":
|
((thd->lex->all_selects_list != sl) ?
|
||||||
"SIMPLE"):
|
primary_key_name : "SIMPLE"):
|
||||||
((sl == first)?
|
((sl == first)?
|
||||||
((sl->linkage == DERIVED_TABLE_TYPE) ?
|
((sl->linkage == DERIVED_TABLE_TYPE) ?
|
||||||
"DERIVED":
|
"DERIVED":
|
||||||
((sl->uncacheable & UNCACHEABLE_DEPENDENT)?
|
((uncacheable & UNCACHEABLE_DEPENDENT) ?
|
||||||
"DEPENDENT SUBQUERY":
|
"DEPENDENT SUBQUERY":
|
||||||
(sl->uncacheable?"UNCACHEABLE SUBQUERY":
|
(uncacheable?"UNCACHEABLE SUBQUERY":
|
||||||
"SUBQUERY"))):
|
"SUBQUERY"))):
|
||||||
((sl->uncacheable & UNCACHEABLE_DEPENDENT)?
|
((uncacheable & UNCACHEABLE_DEPENDENT) ?
|
||||||
"DEPENDENT UNION":
|
"DEPENDENT UNION":
|
||||||
sl->uncacheable?"UNCACHEABLE UNION":
|
uncacheable?"UNCACHEABLE UNION":
|
||||||
"UNION"))),
|
"UNION"))),
|
||||||
result);
|
result);
|
||||||
if (res)
|
if (res)
|
||||||
|
Reference in New Issue
Block a user