summaryrefslogtreecommitdiff
path: root/sql/item.h
diff options
context:
space:
mode:
Diffstat (limited to 'sql/item.h')
-rw-r--r--sql/item.h498
1 files changed, 333 insertions, 165 deletions
diff --git a/sql/item.h b/sql/item.h
index b13438b248f..cda2ab73c4a 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -1,7 +1,8 @@
#ifndef SQL_ITEM_INCLUDED
#define SQL_ITEM_INCLUDED
-/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2011, Oracle and/or its affiliates.
+ Copyright (c) 2009-2011 Monty Program Ab
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -28,6 +29,10 @@
#include "thr_malloc.h" /* sql_calloc */
#include "field.h" /* Derivation */
+C_MODE_START
+#include <ma_dyncol.h>
+C_MODE_END
+
static inline
bool trace_unsupported_func(const char *where, const char *processor_name)
{
@@ -506,6 +511,17 @@ public:
};
+struct st_dyncall_create_def
+{
+ Item *num, *value;
+ CHARSET_INFO *cs;
+ uint len, frac;
+ DYNAMIC_COLUMN_TYPE type;
+};
+
+typedef struct st_dyncall_create_def DYNCALL_CREATE_DEF;
+
+
typedef bool (Item::*Item_processor) (uchar *arg);
/*
Analyzer function
@@ -522,10 +538,24 @@ typedef bool (Item::*Item_analyzer) (uchar **argp);
typedef Item* (Item::*Item_transformer) (uchar *arg);
typedef void (*Cond_traverser) (const Item *item, void *arg);
+class Item_equal;
+class COND_EQUAL;
+
class Item {
Item(const Item &); /* Prevent use of these */
void operator=(Item &);
+ /**
+ The index in the JOIN::join_tab array of the JOIN_TAB this Item is attached
+ to. Items are attached (or 'pushed') to JOIN_TABs during optimization by the
+ make_cond_for_table procedure. During query execution, this item is
+ evaluated when the join loop reaches the corresponding JOIN_TAB.
+
+ If the value of join_tab_idx >= MAX_TABLES, this means that there is no
+ corresponding JOIN_TAB.
+ */
+ uint join_tab_idx;
+
public:
static void *operator new(size_t size) throw ()
{ return sql_alloc(size); }
@@ -572,16 +602,23 @@ public:
Item *next;
uint32 max_length; /* Maximum length, in bytes */
/*
- TODO: convert name and name_length fields into String to keep them in sync
- (see bug #11829681/60295 etc).
+ TODO: convert name and name_length fields into LEX_STRING to keep them in
+ sync (see bug #11829681/60295 etc). Then also remove some strlen(name)
+ calls.
*/
uint name_length; /* Length of name */
int8 marker;
uint8 decimals;
bool maybe_null; /* If item may be null */
+ bool in_rollup; /* If used in GROUP BY list
+ of a query with ROLLUP */
bool null_value; /* if item is null */
bool unsigned_flag;
- bool with_sum_func;
+ bool with_sum_func; /* True if item contains a sum func */
+ /**
+ True if any item except Item_sum_func contains a field. Set during parsing.
+ */
+ bool with_field;
bool fixed; /* If item fixed with fix_fields */
bool is_autogenerated_name; /* indicate was name of this Item
autogenerated or set by user */
@@ -621,10 +658,17 @@ public:
virtual void fix_after_pullout(st_select_lex *new_parent, Item **ref) {};
/*
- should be used in case where we are sure that we do not need
+ This method should be used in case where we are sure that we do not need
complete fix_fields() procedure.
+ Usually this method is used by the optimizer when it has to create a new
+ item out of other already fixed items. For example, if the optimizer has
+ to create a new Item_func for an inferred equality whose left and right
+ parts are already fixed items. In some cases the optimizer cannot use
+ directly fixed items as the arguments of the created functional item,
+ but rather uses intermediate type conversion items. Then the method is
+ supposed to be applied recursively.
*/
- inline void quick_fix_field() { fixed= 1; }
+ virtual inline void quick_fix_field() { fixed= 1; }
/* Function returns 1 on overflow and -1 on fatal errors */
int save_in_field_no_warnings(Field *field, bool no_conversions);
virtual int save_in_field(Field *field, bool no_conversions);
@@ -634,11 +678,20 @@ public:
{ return save_in_field(field, 1); }
virtual bool send(Protocol *protocol, String *str);
virtual bool eq(const Item *, bool binary_cmp) const;
+ /* result_type() of an item specifies how the value should be returned */
virtual Item_result result_type() const { return REAL_RESULT; }
- virtual Item_result cast_to_int_type() const { return result_type(); }
+ /* ... while cmp_type() specifies how it should be compared */
+ virtual Item_result cmp_type() const;
+ virtual Item_result cast_to_int_type() const { return cmp_type(); }
virtual enum_field_types string_field_type() const;
virtual enum_field_types field_type() const;
virtual enum Type type() const =0;
+ /*
+ real_type() is the type of base item. This is same as type() for
+ most items, except Item_ref() and Item_cache_wrapper() where it
+ shows the type for the underlaying item.
+ */
+ virtual enum Type real_type() const { return type(); }
/*
Return information about function monotonicity. See comment for
@@ -862,6 +915,7 @@ public:
String *val_string_from_real(String *str);
String *val_string_from_int(String *str);
String *val_string_from_decimal(String *str);
+ String *val_string_from_date(String *str);
my_decimal *val_decimal_from_real(my_decimal *decimal_value);
my_decimal *val_decimal_from_int(my_decimal *decimal_value);
my_decimal *val_decimal_from_string(my_decimal *decimal_value);
@@ -878,6 +932,8 @@ public:
/* This is also used to create fields in CREATE ... SELECT: */
virtual Field *tmp_table_field(TABLE *t_arg) { return 0; }
virtual const char *full_name() const { return name ? name : "???"; }
+ const char *field_name_or_null()
+ { return real_item()->type() == Item::FIELD_ITEM ? name : NULL; }
/*
*result* family of methods is analog of *val* family (see above) but
@@ -892,13 +948,18 @@ public:
{ return val_decimal(val); }
virtual bool val_bool_result() { return val_bool(); }
virtual bool is_null_result() { return is_null(); }
-
+ /*
+ Returns 1 if result type and collation for val_str() can change between
+ calls
+ */
+ virtual bool dynamic_result() { return 0; }
/*
Bitmap of tables used by item
(note: if you need to check dependencies on individual columns, check out
class Field_enumerator)
*/
virtual table_map used_tables() const { return (table_map) 0L; }
+ virtual table_map all_used_tables() const { return used_tables(); }
/*
Return table map of tables that can't be NULL tables (tables that are
used in a context where if they would contain a NULL row generated
@@ -953,6 +1014,7 @@ public:
}
void print_item_w_name(String *, enum_query_type query_type);
+ void print_value(String *);
virtual void update_used_tables() {}
virtual void split_sum_func(THD *thd, Item **ref_pointer_array,
List<Item> &fields) {}
@@ -960,7 +1022,9 @@ public:
void split_sum_func2(THD *thd, Item **ref_pointer_array, List<Item> &fields,
Item **ref, bool skip_registered);
virtual bool get_date(MYSQL_TIME *ltime,uint fuzzydate);
- virtual bool get_time(MYSQL_TIME *ltime);
+ bool get_time(MYSQL_TIME *ltime)
+ { return get_date(ltime, TIME_TIME_ONLY | TIME_FUZZY_DATE); }
+ bool get_seconds(ulonglong *sec, ulong *sec_part);
virtual bool get_date_result(MYSQL_TIME *ltime,uint fuzzydate)
{ return get_date(ltime,fuzzydate); }
/*
@@ -1075,10 +1139,14 @@ public:
virtual bool reset_query_id_processor(uchar *query_id_arg) { return 0; }
virtual bool is_expensive_processor(uchar *arg) { return 0; }
virtual bool register_field_in_read_map(uchar *arg) { return 0; }
- virtual bool cache_const_expr_analyzer(uchar **arg);
- virtual Item* cache_const_expr_transformer(uchar *arg);
+ virtual bool register_field_in_write_map(uchar *arg) { return 0; }
virtual bool enumerate_field_refs_processor(uchar *arg) { return 0; }
virtual bool mark_as_eliminated_processor(uchar *arg) { return 0; }
+ virtual bool eliminate_subselect_processor(uchar *arg) { return 0; }
+ virtual bool set_fake_select_as_master_processor(uchar *arg) { return 0; }
+ virtual bool view_used_tables_processor(uchar *arg) { return 0; }
+ virtual bool eval_not_null_tables(uchar *opt_arg) { return 0; }
+ virtual bool clear_sum_processor(uchar *opt_arg) { return 0; }
/* To call bool function for all arguments */
struct bool_func_call_args
@@ -1094,12 +1162,16 @@ public:
(this->*(info->bool_function))();
return FALSE;
}
+
/*
The next function differs from the previous one that a bitmap to be updated
is passed as uchar *arg.
*/
virtual bool register_field_in_bitmap(uchar *arg) { return 0; }
+ bool cache_const_expr_analyzer(uchar **arg);
+ Item* cache_const_expr_transformer(uchar *arg);
+
/*
Check if a partition function is allowed
SYNOPSIS
@@ -1167,12 +1239,23 @@ public:
return FALSE;
}
+ /*
+ The enumeration Subst_constraint is currently used only in implementations
+ of the virtual function subst_argument_checker.
+ */
+ enum Subst_constraint
+ {
+ NO_SUBST= 0, /* No substitution for a field is allowed */
+ ANY_SUBST, /* Any substitution for a field is allowed */
+ IDENTITY_SUBST /* Substitution for a field is allowed if any two
+ different values of the field type are not equal */
+ };
+
virtual bool subst_argument_checker(uchar **arg)
- {
- if (*arg)
- *arg= NULL;
- return TRUE;
+ {
+ return (*arg != NULL);
}
+
/*
@brief
Processor used to check acceptability of an item in the defining
@@ -1203,6 +1286,15 @@ public:
{
return FALSE;
}
+ struct Collect_deps_prm
+ {
+ int nest_level;
+ List<Item> *parameters;
+ };
+ /**
+ Collect outer references
+ */
+ virtual bool collect_outer_ref_processor(uchar *arg) {return FALSE; }
/**
Find a function of a given type
@@ -1270,47 +1362,17 @@ public:
{
return 0;
}
- /*
- result_as_longlong() must return TRUE for Items representing DATE/TIME
- functions and DATE/TIME table fields.
- Those Items have result_type()==STRING_RESULT (and not INT_RESULT), but
- their values should be compared as integers (because the integer
- representation is more precise than the string one).
- */
- virtual bool result_as_longlong() { return FALSE; }
- inline bool is_datetime() const
- {
- switch (field_type())
- {
- case MYSQL_TYPE_DATE:
- case MYSQL_TYPE_DATETIME:
- case MYSQL_TYPE_TIMESTAMP:
- return TRUE;
- default:
- break;
- }
- return FALSE;
- }
/**
Check whether this and the given item has compatible comparison context.
Used by the equality propagation. See Item_field::equal_fields_propagator.
@return
- TRUE if the context is the same or if fields could be
- compared as DATETIME values by the Arg_comparator.
+ TRUE if the context is the same
FALSE otherwise.
*/
inline bool has_compatible_context(Item *item) const
{
- /* Same context. */
- if (cmp_context == (Item_result)-1 || item->cmp_context == cmp_context)
- return TRUE;
- /* DATETIME comparison context. */
- if (is_datetime())
- return item->is_datetime() || item->cmp_context == STRING_RESULT;
- if (item->is_datetime())
- return is_datetime() || cmp_context == STRING_RESULT;
- return FALSE;
+ return cmp_context == IMPOSSIBLE_RESULT || item->cmp_context == cmp_context;
}
/*
Test whether an expression is expensive to compute. Used during
@@ -1362,19 +1424,53 @@ public:
else
max_length= (uint32) max_result_length;
}
- void fix_length_and_charset_datetime(uint32 max_char_length_arg)
- {
- collation.set(&my_charset_numeric, DERIVATION_NUMERIC, MY_REPERTOIRE_ASCII);
- fix_char_length(max_char_length_arg);
- }
/*
Return TRUE if the item points to a column of an outer-joined table.
*/
virtual bool is_outer_field() const { DBUG_ASSERT(fixed); return FALSE; }
- Item* set_expr_cache(THD *thd, List<Item*> &depends_on);
+ Item* set_expr_cache(THD *thd);
virtual Item *get_cached_item() { return NULL; }
+
+ virtual Item_equal *get_item_equal() { return NULL; }
+ virtual void set_item_equal(Item_equal *item_eq) {};
+ virtual Item_equal *find_item_equal(COND_EQUAL *cond_equal) { return NULL; }
+ /**
+ Set the join tab index to the minimal (left-most) JOIN_TAB to which this
+ Item is attached. The number is an index is depth_first_tab() traversal
+ order.
+ */
+ virtual void set_join_tab_idx(uint join_tab_idx_arg)
+ {
+ if (join_tab_idx_arg < join_tab_idx)
+ join_tab_idx= join_tab_idx_arg;
+ }
+ virtual uint get_join_tab_idx() { return join_tab_idx; }
+
+ table_map view_used_tables(TABLE_LIST *view)
+ {
+ view->view_used_tables= 0;
+ walk(&Item::view_used_tables_processor, 0, (uchar *) view);
+ return view->view_used_tables;
+ }
+
+ /**
+ Collect and add to the list cache parameters for this Item.
+
+ @note Now implemented only for subqueries and in_optimizer,
+ if we need it for general function then this method should
+ be defined for Item_func.
+ */
+ virtual void get_cache_parameters(List<Item> &parameters) { };
};
+
+/**
+ Compare two Items for List<Item>::add_unique()
+*/
+
+bool cmp_items(Item *a, Item *b);
+
+
/*
Class to be used to enumerate all field references in an item tree. This
includes references to outside but not fields of the tables within a
@@ -1808,10 +1904,15 @@ public:
Item_ident(TABLE_LIST *view_arg, const char *field_name_arg);
const char *full_name() const;
void cleanup();
+ st_select_lex *get_depended_from() const;
bool remove_dependence_processor(uchar * arg);
virtual void print(String *str, enum_query_type query_type);
virtual bool change_context_processor(uchar *cntx)
{ context= (Name_resolution_context *)cntx; return FALSE; }
+ /**
+ Collect outer references
+ */
+ virtual bool collect_outer_ref_processor(uchar *arg);
friend bool insert_fields(THD *thd, Name_resolution_context *context,
const char *db_name,
const char *table_name, List_iterator<Item> *it,
@@ -1842,9 +1943,6 @@ public:
};
-class Item_equal;
-class COND_EQUAL;
-
class Item_field :public Item_ident
{
protected:
@@ -1900,13 +1998,14 @@ public:
int save_in_field(Field *field,bool no_conversions);
void save_org_in_field(Field *field);
table_map used_tables() const;
+ table_map all_used_tables() const;
enum Item_result result_type () const
{
return field->result_type();
}
Item_result cast_to_int_type() const
{
- return field->cast_to_int_type();
+ return field->cmp_type();
}
enum_field_types field_type() const
{
@@ -1921,7 +2020,6 @@ public:
Field *tmp_table_field(TABLE *t_arg) { return result_field; }
bool get_date(MYSQL_TIME *ltime,uint fuzzydate);
bool get_date_result(MYSQL_TIME *ltime,uint fuzzydate);
- bool get_time(MYSQL_TIME *ltime);
bool is_null() { return field->is_null(); }
void update_null_value();
Item *get_tmp_table_item(THD *thd);
@@ -1929,16 +2027,15 @@ public:
bool add_field_to_set_processor(uchar * arg);
bool find_item_in_field_list_processor(uchar *arg);
bool register_field_in_read_map(uchar *arg);
+ bool register_field_in_write_map(uchar *arg);
bool register_field_in_bitmap(uchar *arg);
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
bool vcol_in_partition_func_processor(uchar *bool_arg);
bool check_vcol_func_processor(uchar *arg) { return FALSE;}
bool enumerate_field_refs_processor(uchar *arg);
void cleanup();
- bool result_as_longlong()
- {
- return field->can_be_compared_as_longlong();
- }
+ Item_equal *get_item_equal() { return item_equal; }
+ void set_item_equal(Item_equal *item_eq) { item_equal= item_eq; }
Item_equal *find_item_equal(COND_EQUAL *cond_equal);
bool subst_argument_checker(uchar **arg);
Item *equal_fields_propagator(uchar *arg);
@@ -2096,6 +2193,7 @@ public:
Item_param(uint pos_in_query_arg);
enum Item_result result_type () const { return item_result_type; }
+ enum Item_result cast_to_int_type() const { return item_result_type; }
enum Type type() const { return item_type; }
enum_field_types field_type() const { return param_type; }
@@ -2103,7 +2201,6 @@ public:
longlong val_int();
my_decimal *val_decimal(my_decimal*);
String *val_str(String*);
- bool get_time(MYSQL_TIME *tm);
bool get_date(MYSQL_TIME *tm, uint fuzzydate);
int save_in_field(Field *field, bool no_conversions);
@@ -2223,19 +2320,31 @@ class Item_uint :public Item_int
{
public:
Item_uint(const char *str_arg, uint length);
- Item_uint(ulonglong i) :Item_int((ulonglong) i, 10) {}
+ Item_uint(ulonglong i) :Item_int(i, 10) {}
Item_uint(const char *str_arg, longlong i, uint length);
double val_real()
{ DBUG_ASSERT(fixed == 1); return ulonglong2double((ulonglong)value); }
String *val_str(String*);
Item *clone_item() { return new Item_uint(name, value, max_length); }
- int save_in_field(Field *field, bool no_conversions);
virtual void print(String *str, enum_query_type query_type);
Item_num *neg ();
uint decimal_precision() const { return max_length; }
};
+class Item_datetime :public Item_int
+{
+protected:
+ MYSQL_TIME ltime;
+public:
+ Item_datetime() :Item_int(0) { unsigned_flag=0; }
+ int save_in_field(Field *field, bool no_conversions);
+ longlong val_int();
+ double val_real() { return (double)val_int(); }
+ void set(longlong packed);
+};
+
+
/* decimal (fixed point) constant */
class Item_decimal :public Item_num
{
@@ -2479,14 +2588,16 @@ private:
longlong
-longlong_from_string_with_check (CHARSET_INFO *cs, const char *cptr, char *end);
+longlong_from_string_with_check(CHARSET_INFO *cs, const char *cptr,
+ const char *end);
double
-double_from_string_with_check (CHARSET_INFO *cs, const char *cptr, char *end);
+double_from_string_with_check(CHARSET_INFO *cs, const char *cptr,
+ const char *end);
class Item_static_string_func :public Item_string
{
const char *func_name;
- public:
+public:
Item_static_string_func(const char *name_par, const char *str, uint length,
CHARSET_INFO *cs,
Derivation dv= DERIVATION_COERCIBLE)
@@ -2526,10 +2637,11 @@ class Item_return_date_time :public Item_partition_func_safe_string
{
enum_field_types date_time_field_type;
public:
- Item_return_date_time(const char *name_arg, enum_field_types field_type_arg)
- :Item_partition_func_safe_string(name_arg, 0, &my_charset_bin),
+ Item_return_date_time(const char *name_arg, uint length_arg,
+ enum_field_types field_type_arg)
+ :Item_partition_func_safe_string(name_arg, length_arg, &my_charset_bin),
date_time_field_type(field_type_arg)
- { }
+ { decimals= 0; }
enum_field_types field_type() const { return date_time_field_type; }
};
@@ -2660,11 +2772,12 @@ public:
enum Ref_Type { REF, DIRECT_REF, VIEW_REF, OUTER_REF, AGGREGATE_REF };
Field *result_field; /* Save result here */
Item **ref;
+ bool reference_trough_name;
Item_ref(Name_resolution_context *context_arg,
const char *db_arg, const char *table_name_arg,
const char *field_name_arg)
:Item_ident(context_arg, db_arg, table_name_arg, field_name_arg),
- result_field(0), ref(0) {}
+ result_field(0), ref(0), reference_trough_name(1) {}
/*
This constructor is used in two scenarios:
A) *item = NULL
@@ -2689,6 +2802,8 @@ public:
Item_ref(THD *thd, Item_ref *item)
:Item_ident(thd, item), result_field(item->result_field), ref(item->ref) {}
enum Type type() const { return REF_ITEM; }
+ enum Type real_type() const { return ref ? (*ref)->type() :
+ REF_ITEM; }
bool eq(const Item *item, bool binary_cmp) const
{
Item *it= ((Item *) item)->real_item();
@@ -2720,20 +2835,16 @@ public:
Field *get_tmp_table_field()
{ return result_field ? result_field : (*ref)->get_tmp_table_field(); }
Item *get_tmp_table_item(THD *thd);
- table_map used_tables() const
- {
- return depended_from ? OUTER_REF_TABLE_BIT : (*ref)->used_tables();
- }
- void update_used_tables()
- {
- if (!depended_from)
- (*ref)->update_used_tables();
- }
+ table_map used_tables() const;
+ void update_used_tables();
bool const_item() const
{
return (*ref)->const_item();
}
- table_map not_null_tables() const { return (*ref)->not_null_tables(); }
+ table_map not_null_tables() const
+ {
+ return depended_from ? 0 : (*ref)->not_null_tables();
+ }
void set_result_field(Field *field) { result_field= field; }
bool is_result_field() { return 1; }
void save_in_result_field(bool no_conversions)
@@ -2752,6 +2863,9 @@ public:
else
return FALSE;
}
+ Item* transform(Item_transformer, uchar *arg);
+ Item* compile(Item_analyzer analyzer, uchar **arg_p,
+ Item_transformer transformer, uchar *arg_t);
bool enumerate_field_refs_processor(uchar *arg)
{ return (*ref)->enumerate_field_refs_processor(arg); }
void no_rows_in_result()
@@ -2763,10 +2877,6 @@ public:
(*ref)->restore_to_before_no_rows_in_result();
}
virtual void print(String *str, enum_query_type query_type);
- bool result_as_longlong()
- {
- return (*ref)->result_as_longlong();
- }
void cleanup();
Item_field *filed_for_view_update()
{ return (*ref)->filed_for_view_update(); }
@@ -2803,12 +2913,7 @@ public:
{
return trace_unsupported_by_check_vcol_func_processor("ref");
}
- bool get_time(MYSQL_TIME *ltime)
- {
- DBUG_ASSERT(fixed);
- return (*ref)->get_time(ltime);
- }
- virtual bool basic_const_item() const { return ref && (*ref)->basic_const_item(); }
+ bool basic_const_item() const { return ref && (*ref)->basic_const_item(); }
bool is_outer_field() const
{
DBUG_ASSERT(fixed);
@@ -2852,6 +2957,40 @@ public:
virtual Ref_Type ref_type() { return DIRECT_REF; }
};
+
+/**
+ This class is the same as Item_direct_ref but created to wrap Item_ident
+ before fix_fields() call
+*/
+
+class Item_direct_ref_to_ident :public Item_direct_ref
+{
+ Item_ident *ident;
+public:
+ Item_direct_ref_to_ident(Item_ident *item)
+ :Item_direct_ref(item->context, (Item**)&item, item->table_name, item->field_name,
+ FALSE)
+ {
+ ident= item;
+ ref= (Item**)&ident;
+ }
+
+ bool fix_fields(THD *thd, Item **it)
+ {
+ DBUG_ASSERT(ident->type() == FIELD_ITEM || ident->type() == REF_ITEM);
+ if ((!ident->fixed && ident->fix_fields(thd, ref)) ||
+ ident->check_cols(1))
+ return TRUE;
+ set_properties();
+ return FALSE;
+ }
+
+ virtual void print(String *str, enum_query_type query_type)
+ { ident->print(str, query_type); }
+
+};
+
+
class Item_cache;
class Expression_cache;
@@ -2874,8 +3013,11 @@ private:
*/
Item_cache *expr_value;
+ List<Item> parameters;
+
Item *check_cache();
- inline void cache();
+ void cache();
+ void init_on_demand();
public:
Item_cache_wrapper(Item *item_arg);
@@ -2883,9 +3025,9 @@ public:
const char *func_name() const { return "<expr_cache>"; }
enum Type type() const { return EXPR_CACHE_ITEM; }
- virtual Item *get_cached_item() { return orig_item; }
+ enum Type real_type() const { return orig_item->type(); }
- bool set_cache(THD *thd, List<Item*> &depends_on);
+ bool set_cache(THD *thd);
bool fix_fields(THD *thd, Item **it);
void fix_length_and_dec() {}
@@ -2900,7 +3042,6 @@ public:
bool val_bool();
bool is_null();
bool get_date(MYSQL_TIME *ltime, uint fuzzydate);
- bool get_time(MYSQL_TIME *ltime);
bool send(Protocol *protocol, String *buffer);
void save_org_in_field(Field *field)
{
@@ -2940,7 +3081,6 @@ public:
}
bool enumerate_field_refs_processor(uchar *arg)
{ return orig_item->enumerate_field_refs_processor(arg); }
- bool result_as_longlong() { return orig_item->result_as_longlong(); }
Item_field *filed_for_view_update()
{ return orig_item->filed_for_view_update(); }
@@ -2964,6 +3104,9 @@ public:
if (result_type() == ROW_RESULT)
orig_item->bring_value();
}
+ virtual bool is_expensive() { return orig_item->is_expensive(); }
+ bool is_expensive_processor(uchar *arg)
+ { return orig_item->is_expensive_processor(arg); }
bool check_vcol_func_processor(uchar *arg)
{
return trace_unsupported_by_check_vcol_func_processor("cache");
@@ -2977,17 +3120,21 @@ public:
*/
class Item_direct_view_ref :public Item_direct_ref
{
+ Item_equal *item_equal;
+ TABLE_LIST *view;
public:
Item_direct_view_ref(Name_resolution_context *context_arg, Item **item,
- const char *table_name_arg,
- const char *field_name_arg)
- :Item_direct_ref(context_arg, item, table_name_arg, field_name_arg) {}
+ const char *table_name_arg,
+ const char *field_name_arg,
+ TABLE_LIST *view_arg)
+ :Item_direct_ref(context_arg, item, table_name_arg, field_name_arg),
+ item_equal(0), view(view_arg) {}
/* Constructor need to process subselect with temporary tables (see Item) */
Item_direct_view_ref(THD *thd, Item_direct_ref *item)
- :Item_direct_ref(thd, item) {}
+ :Item_direct_ref(thd, item), item_equal(0) {}
Item_direct_view_ref(TABLE_LIST *view_arg, Item **item,
const char *field_name_arg)
- :Item_direct_ref(view_arg, item, field_name_arg)
+ :Item_direct_ref(view_arg, item, field_name_arg), item_equal(0)
{}
bool fix_fields(THD *, Item **);
@@ -2999,6 +3146,25 @@ public:
return item;
}
virtual Ref_Type ref_type() { return VIEW_REF; }
+ Item_equal *get_item_equal() { return item_equal; }
+ void set_item_equal(Item_equal *item_eq) { item_equal= item_eq; }
+ Item_equal *find_item_equal(COND_EQUAL *cond_equal);
+ bool subst_argument_checker(uchar **arg);
+ Item *equal_fields_propagator(uchar *arg);
+ Item *replace_equal_field(uchar *arg);
+ table_map used_tables() const;
+ bool walk(Item_processor processor, bool walk_subquery, uchar *arg)
+ {
+ return (*ref)->walk(processor, walk_subquery, arg) ||
+ (this->*processor)(arg);
+ }
+ bool view_used_tables_processor(uchar *arg)
+ {
+ TABLE_LIST *view_arg= (TABLE_LIST *) arg;
+ if (view_arg == view)
+ view_arg->view_used_tables|= (*ref)->used_tables();
+ return 0;
+ }
};
@@ -3089,15 +3255,7 @@ public:
bool val_bool();
bool get_date(MYSQL_TIME *ltime, uint fuzzydate);
virtual void print(String *str, enum_query_type query_type);
- /*
- we add RAND_TABLE_BIT to prevent moving this item from HAVING to WHERE
- */
- table_map used_tables() const
- {
- return (depended_from ?
- OUTER_REF_TABLE_BIT :
- (*ref)->used_tables() | RAND_TABLE_BIT);
- }
+ table_map used_tables() const;
};
/*
@@ -3358,6 +3516,17 @@ public:
value.
*/
+/*
+ Cached_item_XXX objects are not exactly caches. They do the following:
+
+ Each Cached_item_XXX object has
+ - its source item
+ - saved value of the source item
+ - cmp() method that compares the saved value with the current value of the
+ source item, and if they were not equal saves item's value into the saved
+ value.
+*/
+
class Cached_item :public Sql_alloc
{
public:
@@ -3476,7 +3645,8 @@ public:
{
return Item_field::save_in_field(field_arg, no_conversions);
}
- /*
+ enum Type type() const { return INSERT_VALUE_ITEM; }
+ /*
We use RAND_TABLE_BIT to prevent Item_insert_value from
being treated as a constant and precalculated before execution
*/
@@ -3582,6 +3752,13 @@ private:
};
+/**
+ @todo
+ Implement the is_null() method for this class. Currently calling is_null()
+ on any Item_cache object resolves to Item::is_null(), which reutns FALSE
+ for any value.
+*/
+
class Item_cache: public Item_basic_constant
{
protected:
@@ -3665,24 +3842,12 @@ public:
return (value_cached || cache_value()) && !null_value;
}
- /**
- If this item caches a field value, return pointer to underlying field.
-
- @return Pointer to field, or NULL if this is not a cache for a field value.
- */
- Field* field() { return cached_field; }
-
virtual void store(Item *item);
virtual bool cache_value()= 0;
bool basic_const_item() const
{ return test(example && example->basic_const_item());}
virtual void clear() { null_value= TRUE; value_cached= FALSE; }
- Item_result result_type() const
- {
- if (!example)
- return INT_RESULT;
- return Field::result_merge_type(example->field_type());
- }
+ bool is_null() { return null_value; }
};
@@ -3691,20 +3856,41 @@ class Item_cache_int: public Item_cache
protected:
longlong value;
public:
- Item_cache_int(): Item_cache(),
+ Item_cache_int(): Item_cache(MYSQL_TYPE_LONGLONG),
value(0) {}
Item_cache_int(enum_field_types field_type_arg):
Item_cache(field_type_arg), value(0) {}
- virtual void store(Item *item){ Item_cache::store(item); }
- void store_longlong(Item *item, longlong val_arg);
double val_real();
longlong val_int();
String* val_str(String *str);
my_decimal *val_decimal(my_decimal *);
enum Item_result result_type() const { return INT_RESULT; }
- bool result_as_longlong() { return TRUE; }
bool cache_value();
+ int save_in_field(Field *field, bool no_conversions);
+};
+
+
+class Item_cache_temporal: public Item_cache_int
+{
+public:
+ Item_cache_temporal(enum_field_types field_type_arg);
+ String* val_str(String *str);
+ bool cache_value();
+ bool get_date(MYSQL_TIME *ltime, uint fuzzydate);
+ int save_in_field(Field *field, bool no_conversions);
+ void store_packed(longlong val_arg);
+ /*
+ Having a clone_item method tells optimizer that this object
+ is a constant and need not be optimized further.
+ Important when storing packed datetime values.
+ */
+ Item *clone_item()
+ {
+ Item_cache_temporal *item= new Item_cache_temporal(cached_field_type);
+ item->store_packed(value);
+ return item;
+ }
};
@@ -3712,7 +3898,7 @@ class Item_cache_real: public Item_cache
{
double value;
public:
- Item_cache_real(): Item_cache(),
+ Item_cache_real(): Item_cache(MYSQL_TYPE_DOUBLE),
value(0) {}
double val_real();
@@ -3729,7 +3915,7 @@ class Item_cache_decimal: public Item_cache
protected:
my_decimal decimal_value;
public:
- Item_cache_decimal(): Item_cache() {}
+ Item_cache_decimal(): Item_cache(MYSQL_TYPE_NEWDECIMAL) {}
double val_real();
longlong val_int();
@@ -3835,40 +4021,6 @@ public:
};
-class Item_cache_datetime: public Item_cache
-{
-protected:
- String str_value;
- longlong int_value;
- bool str_value_cached;
-public:
- Item_cache_datetime(enum_field_types field_type_arg):
- Item_cache(field_type_arg), int_value(0), str_value_cached(0)
- {
- cmp_context= STRING_RESULT;
- }
-
- void store(Item *item, longlong val_arg);
- void store(Item *item);
- double val_real();
- longlong val_int();
- String* val_str(String *str);
- my_decimal *val_decimal(my_decimal *);
- enum Item_result result_type() const { return STRING_RESULT; }
- bool result_as_longlong() { return TRUE; }
- /*
- In order to avoid INT <-> STRING conversion of a DATETIME value
- two cache_value functions are introduced. One (cache_value) caches STRING
- value, another (cache_value_int) - INT value. Thus this cache item
- completely relies on the ability of the underlying item to do the
- correct conversion.
- */
- bool cache_value_int();
- bool cache_value();
- void clear() { Item_cache::clear(); str_value_cached= FALSE; }
-};
-
-
/*
Item_type_holder used to store type. name, length of Item for UNIONS &
derived tables.
@@ -3969,6 +4121,22 @@ public:
/**
+ Item iterator over List_iterator_fast for Items
+*/
+
+class Item_iterator_list: public Item_iterator
+{
+ List_iterator<Item> list;
+public:
+ Item_iterator_list(List_iterator<Item> &arg_list):
+ list(arg_list) {}
+ void open() { list.rewind(); }
+ Item *next() { return (list++); }
+ void close() {}
+};
+
+
+/**
Item iterator over Item interface for rows
*/