diff options
Diffstat (limited to 'sql/item.h')
-rw-r--r-- | sql/item.h | 243 |
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, |