Commit d24a2296 authored by igor@rurik.mysql.com's avatar igor@rurik.mysql.com

Manual merge

parent f18e0068
......@@ -126,8 +126,8 @@ class Item {
top AND/OR ctructure of WHERE clause to protect it of
optimisation changes in prepared statements
*/
Item(THD *thd, Item &item);
virtual ~Item() { name=0; cleanup(); } /*lint -e1509 */
Item(THD *thd, Item *item);
virtual ~Item() { name=0; } /*lint -e1509 */
void set_name(const char *str,uint length, CHARSET_INFO *cs);
void init_make_field(Send_field *tmp_field,enum enum_field_types type);
virtual void cleanup() { fixed=0; }
......@@ -206,6 +206,7 @@ class Item {
virtual Item *get_tmp_table_item(THD *thd) { return copy_or_same(thd); }
CHARSET_INFO *default_charset() const;
virtual CHARSET_INFO *compare_collation() { return NULL; }
virtual bool walk(Item_processor processor, byte *arg)
{
......@@ -239,6 +240,11 @@ class Item {
/* Used in sql_select.cc:eliminate_not_funcs() */
virtual Item *neg_transformer() { return NULL; }
void delete_self()
{
cleanup();
delete this;
}
};
......@@ -304,7 +310,10 @@ class Item_splocal : public Item
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
......@@ -326,6 +335,11 @@ class Item_splocal : public Item
{
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
st_select_lex *depended_from;
Item_ident(const char *db_name_par,const char *table_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;
bool remove_dependence_processor(byte * arg);
......@@ -362,7 +376,7 @@ class Item_field :public Item_ident
item_equal(0)
{ collation.set(DERIVATION_IMPLICIT); }
// 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);
enum Type type() const { return FIELD_ITEM; }
bool eq(const Item *item, bool binary_cmp) const;
......@@ -393,6 +407,7 @@ class Item_field :public Item_ident
bool get_time(TIME *ltime);
bool is_null() { return field->is_null(); }
Item *get_tmp_table_item(THD *thd);
void cleanup();
Item_equal *find_item_equal(COND_EQUAL *cond_equal);
Item *equal_fields_propagator(byte *arg);
bool replace_equal_field_processor(byte *arg);
......@@ -583,7 +598,7 @@ class Item_string :public Item
CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE)
{
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
ensure that we get the right length if we do use the item
......@@ -599,12 +614,11 @@ class Item_string :public Item
CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE)
{
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;
set_name(name_par,0,cs);
decimals=NOT_FIXED_DEC;
}
~Item_string() {}
enum Type type() const { return STRING_ITEM; }
double val()
{
......@@ -671,7 +685,6 @@ class Item_varbinary :public Item
{
public:
Item_varbinary(const char *str,uint str_length);
~Item_varbinary() {}
enum Type type() const { return VARBIN_ITEM; }
double val() { return (double) Item_varbinary::val_int(); }
longlong val_int();
......@@ -688,8 +701,8 @@ class Item_result_field :public Item /* Item with result field */
Field *result_field; /* Save result here */
Item_result_field() :result_field(0) {}
// Constructor used for Item_sum/Item_cond_and/or (see Item comment)
Item_result_field(THD *thd, Item_result_field &item):
Item(thd, item), result_field(item.result_field)
Item_result_field(THD *thd, Item_result_field *item):
Item(thd, item), result_field(item->result_field)
{}
~Item_result_field() {} /* Required with gcc 2.95 */
Field *get_tmp_table_field() { return result_field; }
......@@ -708,20 +721,25 @@ class Item_result_field :public Item /* Item with result field */
class Item_ref :public Item_ident
{
public:
Field *result_field; /* Save result here */
Field *result_field; /* Save result here */
Item **ref;
Item_ref(const char *db_par, const char *table_name_par,
const char *field_name_par)
:Item_ident(db_par,table_name_par,field_name_par),ref(0) {}
Item_ref(Item **item, const char *table_name_par, const char *field_name_par)
:Item_ident(NullS,table_name_par,field_name_par),ref(item) {}
Item **hook_ptr; /* These two to restore */
Item *orig_item; /* things in 'cleanup()' */
Item_ref(Item **hook, Item *original,const char *db_par,
const char *table_name_par, const char *field_name_par)
: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)
Item_ref(THD *thd, Item_ref &item)
:Item_ident(thd, item), ref(item.ref) {}
Item_ref(THD *thd, Item_ref *item, Item **hook)
:Item_ident(thd, item), ref(item->ref),
hook_ptr(hook), orig_item(hook ? *hook : 0) {}
enum Type type() const { return REF_ITEM; }
bool eq(const Item *item, bool binary_cmp) const
{ return ref && (*ref)->eq(item, binary_cmp); }
~Item_ref() { if (ref && (*ref) && (*ref) != this) delete *ref; }
double val()
{
double tmp=(*ref)->val_result();
......@@ -766,6 +784,7 @@ class Item_ref :public Item_ident
}
Item *real_item() { return *ref; }
void print(String *str);
void cleanup();
};
class Item_in_subselect;
......@@ -776,7 +795,7 @@ class Item_ref_null_helper: public Item_ref
public:
Item_ref_null_helper(Item_in_subselect* master, Item **item,
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();
longlong val_int();
String* val_str(String* s);
......@@ -840,7 +859,6 @@ class Item_copy_string :public Item
name=item->name;
cached_field_type= item->field_type();
}
~Item_copy_string() { delete item; }
enum Type type() const { return COPY_STR_ITEM; }
enum Item_result result_type () const { return STRING_RESULT; }
enum_field_types field_type() const { return cached_field_type; }
......@@ -997,13 +1015,15 @@ class Item_cache: public Item
void set_used_tables(table_map map) { used_table_map= map; }
virtual bool allocate(uint i) { return 0; };
virtual bool setup(Item *item) { example= item; return 0; };
virtual void store(Item *)= 0;
void set_len_n_dec(uint32 max_len, uint8 dec)
virtual bool setup(Item *item)
{
max_length= max_len;
decimals= dec;
}
example= item;
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; }
static Item_cache* get_cache(Item_result type);
table_map used_tables() const { return used_table_map; }
......@@ -1028,7 +1048,7 @@ class Item_cache_real: public Item_cache
double value;
public:
Item_cache_real(): Item_cache() {}
void store(Item *item);
double val() { return value; }
longlong val_int() { return (longlong) (value+(value > 0 ? 0.5 : -0.5)); }
......@@ -1101,6 +1121,11 @@ class Item_cache_row: public Item_cache
bool check_cols(uint c);
bool null_inside();
void bring_value();
void cleanup()
{
Item_cache::cleanup();
values= 0;
}
};
......@@ -1111,6 +1136,7 @@ class Item_type_holder: public Item
{
protected:
Item_result item_type;
Item_result orig_type;
Field *field_example;
public:
Item_type_holder(THD*, Item*);
......@@ -1122,6 +1148,11 @@ class Item_type_holder: public Item
String *val_str(String*);
bool join_types(THD *thd, Item *);
Field *example() { return field_example; }
void cleanup()
{
Item::cleanup();
item_type= orig_type;
}
};
......
......@@ -301,10 +301,11 @@ typedef struct st_qsel_param {
uint imerge_cost_buff_size; /* size of the buffer */
} 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_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);
static SEL_TREE *get_mm_tree(PARAM *param,COND *cond);
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;
quick= 0;
if (free_cond)
{
free_cond=0;
delete cond;
cond= 0;
}
close_cached_file(&file);
}
SQL_SELECT::~SQL_SELECT()
{
cleanup();
}
#undef index // Fix for Unixware 7
QUICK_SELECT_I::QUICK_SELECT_I()
......@@ -1746,7 +1758,8 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
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)
{
DBUG_ENTER("get_mm_parts");
......@@ -1768,7 +1781,8 @@ get_mm_parts(PARAM *param, Field *field, Item_func::Functype type,
DBUG_RETURN(0); // OOM
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)
continue;
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 *
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)
{
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;
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)
{
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));
}
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]) &&
type != Item_func::EQ_FUNC &&
type != Item_func::EQUAL_FUNC)
......@@ -1895,7 +1919,7 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part,
value->result_type() != STRING_RESULT &&
field->cmp_type() != value->result_type())
DBUG_RETURN(0);
if (value->save_in_field(field, 1) > 0)
{
/* 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)
param->table->quick_rows[key]=records;
param->table->quick_key_parts[key]=param->max_key_part+1;
}
DBUG_PRINT("exit", ("Records: %lu", (ulong) 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->null_bit= key_info->key_part[part].null_bit;
}
if (!insert_dynamic(&quick->ranges,(gptr)&range))
return quick;
if (insert_dynamic(&quick->ranges,(gptr)&range))
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:
delete quick;
......@@ -3584,12 +3631,7 @@ int QUICK_RANGE_SELECT::get_next()
int result;
if (range)
{ // Already read through key
/* result=((range->flag & EQ_RANGE) ?
file->index_next_same(record, (byte*) range->min_key,
range->min_length) :
file->index_next(record));
*/
result=((range->flag & (EQ_RANGE | GEOM_FLAG) ) ?
result=((range->flag & (EQ_RANGE | GEOM_FLAG)) ?
file->index_next_same(record, (byte*) range->min_key,
range->min_length) :
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