Commit fd98ed36 authored by unknown's avatar unknown

Manual merge

parent f4353d48
...@@ -126,8 +126,8 @@ public: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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 ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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; }
...@@ -1028,7 +1048,7 @@ class Item_cache_real: public Item_cache ...@@ -1028,7 +1048,7 @@ class Item_cache_real: public Item_cache
double value; double value;
public: public:
Item_cache_real(): Item_cache() {} Item_cache_real(): Item_cache() {}
void store(Item *item); void store(Item *item);
double val() { return value; } double val() { return value; }
longlong val_int() { return (longlong) (value+(value > 0 ? 0.5 : -0.5)); } longlong val_int() { return (longlong) (value+(value > 0 ? 0.5 : -0.5)); }
...@@ -1101,6 +1121,11 @@ public: ...@@ -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 ...@@ -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: ...@@ -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;
}
}; };
......
...@@ -301,10 +301,11 @@ typedef struct st_qsel_param { ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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)
...@@ -1895,7 +1919,7 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part, ...@@ -1895,7 +1919,7 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part,
value->result_type() != STRING_RESULT && value->result_type() != STRING_RESULT &&
field->cmp_type() != value->result_type()) field->cmp_type() != value->result_type())
DBUG_RETURN(0); DBUG_RETURN(0);
if (value->save_in_field(field, 1) > 0) if (value->save_in_field(field, 1) > 0)
{ {
/* This happens when we try to insert a NULL field in a not null column */ /* This happens when we try to insert a NULL field in a not null column */
...@@ -3097,6 +3121,7 @@ check_quick_select(PARAM *param,uint idx,SEL_ARG *tree) ...@@ -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, ...@@ -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() ...@@ -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));
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment