summaryrefslogtreecommitdiff
path: root/sql/item.h
diff options
context:
space:
mode:
Diffstat (limited to 'sql/item.h')
-rw-r--r--sql/item.h243
1 files changed, 184 insertions, 59 deletions
diff --git a/sql/item.h b/sql/item.h
index c8180b4932a..560f1124fb4 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -24,7 +24,6 @@ struct st_table_list;
void item_init(void); /* Init item functions */
class Item_field;
-
/*
"Declared Type Collation"
A combination of collation and its derivation.
@@ -218,23 +217,110 @@ struct Hybrid_type_traits_integer: public Hybrid_type_traits
static const Hybrid_type_traits_integer *instance();
};
+
+void dummy_error_processor(THD *thd, void *data);
+
+void view_error_processor(THD *thd, void *data);
+
+/*
+ Instances of Name_resolution_context store the information necesary for
+ name resolution of Items and other context analysis of a query made in
+ fix_fields().
+
+ This structure is a part of SELECT_LEX, a pointer to this structure is
+ assigned when an item is created (which happens mostly during parsing
+ (sql_yacc.yy)), but the structure itself will be initialized after parsing
+ is complete
+
+ TODO: move subquery of INSERT ... SELECT and CREATE ... SELECT to
+ separate SELECT_LEX which allow to remove tricks of changing this
+ structure before and after INSERT/CREATE and its SELECT to make correct
+ field name resolution.
+*/
+struct Name_resolution_context
+{
+ /*
+ The name resolution context to search in when an Item cannot be
+ resolved in this context (the context of an outer select)
+ */
+ Name_resolution_context *outer_context;
+
+ /*
+ List of tables used to resolve the items of this context. Usually these
+ are tables from the FROM clause of SELECT statement. The exceptions are
+ INSERT ... SELECT and CREATE ... SELECT statements, where SELECT
+ subquery is not moved to a separate SELECT_LEX. For these types of
+ statements we have to change this member dynamically to ensure correct
+ name resolution of different parts of the statement.
+ */
+ TABLE_LIST *table_list;
+
+ /*
+ SELECT_LEX item belong to, in case of merged VIEW it can differ from
+ SELECT_LEX where item was created, so we can't use table_list/field_list
+ from there
+ */
+ st_select_lex *select_lex;
+
+ /*
+ Processor of errors caused during Item name resolving, now used only to
+ hide underlying tables in errors about views (i.e. it substitute some
+ errors for views)
+ */
+ void (*error_processor)(THD *, void *);
+ void *error_processor_data;
+
+ /*
+ When TRUE items are resolved in this context both against the
+ SELECT list and this->table_list. If FALSE, items are resolved
+ only against this->table_list.
+ */
+ bool resolve_in_select_list;
+
+ /*
+ When FALSE we do not check columns right of resolving items, used to
+ prevent rights check on underlying tables of view
+ */
+ bool check_privileges;
+
+ Name_resolution_context()
+ :outer_context(0), table_list(0), select_lex(0),
+ error_processor_data(0),
+ check_privileges(TRUE)
+ {}
+
+ void init()
+ {
+ resolve_in_select_list= FALSE;
+ error_processor= &dummy_error_processor;
+ }
+
+ void resolve_in_table_list_only(TABLE_LIST *tables)
+ {
+ table_list= tables;
+ resolve_in_select_list= FALSE;
+ }
+
+ void process_error(THD *thd)
+ {
+ (*error_processor)(thd, error_processor_data);
+ }
+};
+
+
/*************************************************************************/
typedef bool (Item::*Item_processor)(byte *arg);
typedef Item* (Item::*Item_transformer) (byte *arg);
-
typedef void (*Cond_traverser) (const Item *item, void *arg);
-/*
- See comments for sql_yacc.yy: insert_update_elem rule
- */
-#define MY_ITEM_PREFER_1ST_TABLE 1
class Item {
Item(const Item &); /* Prevent use of these */
void operator=(Item &);
public:
- static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); }
+ static void *operator new(size_t size)
+ { return (void*) sql_alloc((uint) size); }
static void *operator new(size_t size, MEM_ROOT *mem_root)
{ return (void*) alloc_root(mem_root, (uint) size); }
/* Special for SP local variable assignment - reusing slots */
@@ -248,7 +334,8 @@ public:
PROC_ITEM,COND_ITEM, REF_ITEM, FIELD_STD_ITEM,
FIELD_VARIANCE_ITEM, INSERT_VALUE_ITEM,
SUBSELECT_ITEM, ROW_ITEM, CACHE_ITEM, TYPE_HOLDER,
- PARAM_ITEM, TRIGGER_FIELD_ITEM, DECIMAL_ITEM};
+ PARAM_ITEM, TRIGGER_FIELD_ITEM, DECIMAL_ITEM,
+ VIEW_FIXER_ITEM};
enum cond_result { COND_UNDEF,COND_OK,COND_TRUE,COND_FALSE };
@@ -277,7 +364,6 @@ public:
my_bool is_autogenerated_name; /* indicate was name of this Item
autogenerated or set by user */
DTCollation collation;
- uint8 item_flags; /* Flags on how item should be processed */
// alloc & destruct is done as start of select using sql_alloc
Item();
@@ -302,7 +388,7 @@ public:
virtual void cleanup();
virtual void make_field(Send_field *field);
Field *make_string_field(TABLE *table);
- virtual bool fix_fields(THD *, struct st_table_list *, Item **);
+ virtual bool fix_fields(THD *, Item **);
/*
should be used in case where we are sure that we do not need
complete fix_fields() procedure.
@@ -554,6 +640,8 @@ public:
virtual bool remove_fixed(byte * arg) { fixed= 0; return 0; }
virtual bool cleanup_processor(byte *arg);
virtual bool collect_item_field_processor(byte * arg) { return 0; }
+ virtual bool change_context_processor(byte *context) { return 0; }
+
virtual Item *equal_fields_propagator(byte * arg) { return this; }
virtual Item *set_no_const_sub(byte *arg) { return this; }
virtual Item *replace_equal_field(byte * arg) { return this; }
@@ -590,11 +678,6 @@ public:
cleanup();
delete this;
}
- virtual bool set_flags_processor(byte *args)
- {
- this->item_flags|= *((uint8*)args);
- return false;
- }
virtual bool is_splocal() { return 0; } /* Needed for error checking */
};
@@ -631,7 +714,7 @@ public:
Item **this_item_addr(THD *thd, Item **);
Item *this_const_item() const;
- bool fix_fields(THD *, struct st_table_list *, Item **);
+ bool fix_fields(THD *, Item **);
void cleanup();
inline uint get_offset()
@@ -704,7 +787,9 @@ protected:
const char *orig_db_name;
const char *orig_table_name;
const char *orig_field_name;
+
public:
+ Name_resolution_context *context;
const char *db_name;
const char *table_name;
const char *field_name;
@@ -722,13 +807,16 @@ public:
*/
TABLE_LIST *cached_table;
st_select_lex *depended_from;
- Item_ident(const char *db_name_par,const char *table_name_par,
- const char *field_name_par);
+ Item_ident(Name_resolution_context *context_arg,
+ const char *db_name_arg, const char *table_name_arg,
+ const char *field_name_arg);
Item_ident(THD *thd, Item_ident *item);
const char *full_name() const;
void cleanup();
bool remove_dependence_processor(byte * arg);
void print(String *str);
+ virtual bool change_context_processor(byte *cntx)
+ { context= (Name_resolution_context *)cntx; return FALSE; }
};
class Item_equal;
@@ -750,12 +838,9 @@ public:
/* field need any privileges (for VIEW creation) */
bool any_privileges;
- Item_field(const char *db_par,const char *table_name_par,
- const char *field_name_par)
- :Item_ident(db_par,table_name_par,field_name_par),
- field(0), result_field(0), item_equal(0), no_const_subst(0),
- have_privileges(0), any_privileges(0)
- { collation.set(DERIVATION_IMPLICIT); }
+ Item_field(Name_resolution_context *context_arg,
+ const char *db_arg,const char *table_name_arg,
+ const char *field_name_arg);
/*
Constructor needed to process subselect with temporary tables (see Item)
*/
@@ -765,7 +850,7 @@ public:
and database names will live as long as Item_field (this is important
in prepared statements).
*/
- Item_field(THD *thd, Field *field);
+ Item_field(THD *thd, Name_resolution_context *context_arg, Field *field);
/*
If this constructor is used, fix_fields() won't work, because
db_name, table_name and column_name are unknown. It's necessary to call
@@ -785,7 +870,7 @@ public:
bool val_bool_result();
bool send(Protocol *protocol, String *str_arg);
void reset_field(Field *f);
- bool fix_fields(THD *, struct st_table_list *, Item **);
+ bool fix_fields(THD *, Item **);
void make_field(Send_field *tmp_field);
int save_in_field(Field *field,bool no_conversions);
void save_org_in_field(Field *field);
@@ -946,7 +1031,7 @@ public:
bool get_time(TIME *tm);
bool get_date(TIME *tm, uint fuzzydate);
int save_in_field(Field *field, bool no_conversions);
- bool fix_fields(THD *, struct st_table_list *, Item **);
+ bool fix_fields(THD *, Item **);
void set_null();
void set_int(longlong i, uint32 max_length_arg);
@@ -1317,9 +1402,11 @@ protected:
public:
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), result_field(0), ref(0) {}
+ 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) {}
/*
This constructor is used in two scenarios:
A) *item = NULL
@@ -1334,13 +1421,18 @@ public:
TODO we probably fix a superset of problems like in BUG#6658. Check this
with Bar, and if we have a more broader set of problems like this.
*/
- Item_ref(Item **item, const char *table_name_par, const char *field_name_par);
+ Item_ref(Name_resolution_context *context_arg, Item **item,
+ const char *table_name_arg, const char *field_name_arg);
/* Constructor need to process subselect with temporary tables (see Item) */
- Item_ref(THD *thd, Item_ref *item) :Item_ident(thd, item), result_field(item->result_field), ref(item->ref) {}
+ 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; }
bool eq(const Item *item, bool binary_cmp) const
- { return ref && (*ref)->eq(item, binary_cmp); }
+ {
+ Item *it= ((Item *) item)->real_item();
+ return ref && (*ref)->eq(it, binary_cmp);
+ }
double val_real();
longlong val_int();
my_decimal *val_decimal(my_decimal *);
@@ -1354,8 +1446,8 @@ public:
my_decimal *val_decimal_result(my_decimal *);
bool val_bool_result();
bool send(Protocol *prot, String *tmp);
- void make_field(Send_field *field) { (*ref)->make_field(field); }
- bool fix_fields(THD *, struct st_table_list *, Item **);
+ void make_field(Send_field *field);
+ bool fix_fields(THD *, Item **);
int save_in_field(Field *field, bool no_conversions);
void save_org_in_field(Field *field) { (*ref)->save_org_in_field(field); }
enum Item_result result_type () const { return (*ref)->result_type(); }
@@ -1380,6 +1472,8 @@ public:
{ return (*ref)->walk(processor, arg); }
void print(String *str);
void cleanup();
+ Item_field *filed_for_view_update()
+ { return (*ref)->filed_for_view_update(); }
};
@@ -1390,9 +1484,10 @@ public:
class Item_direct_ref :public Item_ref
{
public:
- Item_direct_ref(Item **item, const char *table_name_par,
- const char *field_name_par)
- :Item_ref(item, table_name_par, field_name_par) {}
+ Item_direct_ref(Name_resolution_context *context_arg, Item **item,
+ const char *table_name_arg,
+ const char *field_name_arg)
+ :Item_ref(context_arg, item, table_name_arg, field_name_arg) {}
/* Constructor need to process subselect with temporary tables (see Item) */
Item_direct_ref(THD *thd, Item_direct_ref *item) : Item_ref(thd, item) {}
@@ -1405,6 +1500,24 @@ public:
bool get_date(TIME *ltime,uint fuzzydate);
};
+/*
+ Class for view fields, the same as Item_direct_ref, but call fix_fields
+ of reference if it is not called yet
+*/
+class Item_direct_view_ref :public Item_direct_ref
+{
+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) {}
+ /* 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) {}
+
+ bool fix_fields(THD *, Item **);
+};
+
class Item_in_subselect;
@@ -1413,9 +1526,11 @@ class Item_ref_null_helper: public Item_ref
protected:
Item_in_subselect* owner;
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_null_helper(Name_resolution_context *context_arg,
+ Item_in_subselect* master, Item **item,
+ const char *table_name_arg, const char *field_name_arg)
+ :Item_ref(context_arg, item, table_name_arg, field_name_arg),
+ owner(master) {}
double val_real();
longlong val_int();
String* val_str(String* s);
@@ -1429,10 +1544,11 @@ class Item_null_helper :public Item_ref_null_helper
{
Item *store;
public:
- Item_null_helper(Item_in_subselect* master, Item *item,
- const char *table_name_par, const char *field_name_par)
- :Item_ref_null_helper(master, (store= 0, &store), table_name_par,
- field_name_par),
+ Item_null_helper(Name_resolution_context *context_arg,
+ Item_in_subselect* master, Item *item,
+ const char *table_name_arg, const char *field_name_arg)
+ :Item_ref_null_helper(context_arg, master, (store= 0, &store),
+ table_name_arg, field_name_arg),
store(item)
{ ref= &store; }
void print(String *str);
@@ -1583,13 +1699,17 @@ class Item_default_value : public Item_field
{
public:
Item *arg;
- Item_default_value() :
- Item_field((const char *)NULL, (const char *)NULL, (const char *)NULL), arg(NULL) {}
- Item_default_value(Item *a) :
- Item_field((const char *)NULL, (const char *)NULL, (const char *)NULL), arg(a) {}
+ Item_default_value(Name_resolution_context *context_arg)
+ :Item_field(context_arg, (const char *)NULL, (const char *)NULL,
+ (const char *)NULL),
+ arg(NULL) {}
+ Item_default_value(Name_resolution_context *context_arg, Item *a)
+ :Item_field(context_arg, (const char *)NULL, (const char *)NULL,
+ (const char *)NULL),
+ arg(a) {}
enum Type type() const { return DEFAULT_VALUE_ITEM; }
bool eq(const Item *item, bool binary_cmp) const;
- bool fix_fields(THD *, struct st_table_list *, Item **);
+ bool fix_fields(THD *, Item **);
void print(String *str);
int save_in_field(Field *field_arg, bool no_conversions);
table_map used_tables() const { return (table_map)0L; }
@@ -1618,10 +1738,12 @@ class Item_insert_value : public Item_field
{
public:
Item *arg;
- Item_insert_value(Item *a) :
- Item_field((const char *)NULL, (const char *)NULL, (const char *)NULL), arg(a) {}
+ Item_insert_value(Name_resolution_context *context_arg, Item *a)
+ :Item_field(context_arg, (const char *)NULL, (const char *)NULL,
+ (const char *)NULL),
+ arg(a) {}
bool eq(const Item *item, bool binary_cmp) const;
- bool fix_fields(THD *, struct st_table_list *, Item **);
+ bool fix_fields(THD *, Item **);
void print(String *str);
int save_in_field(Field *field_arg, bool no_conversions)
{
@@ -1683,15 +1805,17 @@ public:
/* Pointer to Table_trigger_list object for table of this trigger */
Table_triggers_list *triggers;
- Item_trigger_field(row_version_type row_ver_par,
- const char *field_name_par):
- Item_field((const char *)NULL, (const char *)NULL, field_name_par),
- row_version(row_ver_par), field_idx((uint)-1)
+ Item_trigger_field(Name_resolution_context *context_arg,
+ row_version_type row_ver_arg,
+ const char *field_name_arg)
+ :Item_field(context_arg,
+ (const char *)NULL, (const char *)NULL, field_name_arg),
+ row_version(row_ver_arg), field_idx((uint)-1)
{}
void setup_field(THD *thd, TABLE *table);
enum Type type() const { return TRIGGER_FIELD_ITEM; }
bool eq(const Item *item, bool binary_cmp) const;
- bool fix_fields(THD *, struct st_table_list *, Item **);
+ bool fix_fields(THD *, Item **);
void print(String *str);
table_map used_tables() const { return (table_map)0L; }
void cleanup();
@@ -1880,7 +2004,7 @@ public:
Item_type_holder(THD*, Item*);
Item_result result_type() const;
- virtual enum_field_types field_type() const { return fld_type; };
+ enum_field_types field_type() const { return fld_type; };
enum Type type() const { return TYPE_HOLDER; }
double val_real();
longlong val_int();
@@ -1892,6 +2016,7 @@ public:
static enum_field_types get_real_type(Item *);
};
+
class st_select_lex;
void mark_select_range_as_dependent(THD *thd,
st_select_lex *last_select,