Commit fd98ed36 authored by unknown's avatar unknown

Manual merge

parent f4353d48
...@@ -126,8 +126,8 @@ class Item { ...@@ -126,8 +126,8 @@ class Item {
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 @@ class Item { ...@@ -206,6 +206,7 @@ class Item {
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 @@ class Item { ...@@ -239,6 +240,11 @@ class Item {
/* 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 @@ class Item_splocal : public Item ...@@ -304,7 +310,10 @@ class Item_splocal : public Item
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 @@ class Item_splocal : public Item ...@@ -326,6 +335,11 @@ class Item_splocal : public Item
{ {
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 @@ class Item_ident :public Item ...@@ -339,7 +353,7 @@ class Item_ident :public Item
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 @@ class Item_field :public Item_ident ...@@ -362,7 +376,7 @@ class Item_field :public Item_ident
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 @@ class Item_field :public Item_ident ...@@ -393,6 +407,7 @@ class Item_field :public Item_ident
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 @@ class Item_string :public Item ...@@ -583,7 +598,7 @@ class Item_string :public Item
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 @@ class Item_string :public Item ...@@ -599,12 +614,11 @@ class Item_string :public Item
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 @@ class Item_result_field :public Item /* Item with result field */ ...@@ -688,8 +701,8 @@ class Item_result_field :public Item /* Item with result field */
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 @@ class Item_result_field :public Item /* Item with result field */ ...@@ -708,20 +721,25 @@ class Item_result_field :public Item /* Item with result field */
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 @@ class Item_ref :public Item_ident ...@@ -766,6 +784,7 @@ class Item_ref :public Item_ident
} }
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 @@ class Item_ref_null_helper: public Item_ref ...@@ -776,7 +795,7 @@ class Item_ref_null_helper: public Item_ref
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 @@ class Item_copy_string :public Item ...@@ -840,7 +859,6 @@ class Item_copy_string :public Item
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 @@ class Item_cache: public Item ...@@ -997,13 +1015,15 @@ class Item_cache: public Item
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 @@ class Item_cache_row: public Item_cache ...@@ -1101,6 +1121,11 @@ class Item_cache_row: public Item_cache
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 @@ class Item_type_holder: public Item ...@@ -1122,6 +1148,11 @@ class Item_type_holder: public Item
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