Name resolution context added (BUG#6443)
This commit is contained in:
parent
d8cb0cbc3f
commit
d3905f3d0e
@ -45,6 +45,8 @@ extern my_bool bitmap_is_prefix(const MY_BITMAP *map, uint prefix_size);
|
|||||||
extern my_bool bitmap_is_set(const MY_BITMAP *map, uint bitmap_bit);
|
extern my_bool bitmap_is_set(const MY_BITMAP *map, uint bitmap_bit);
|
||||||
extern my_bool bitmap_is_set_all(const MY_BITMAP *map);
|
extern my_bool bitmap_is_set_all(const MY_BITMAP *map);
|
||||||
extern my_bool bitmap_is_subset(const MY_BITMAP *map1, const MY_BITMAP *map2);
|
extern my_bool bitmap_is_subset(const MY_BITMAP *map1, const MY_BITMAP *map2);
|
||||||
|
extern my_bool bitmap_test_and_set(MY_BITMAP *map, uint bitmap_bit);
|
||||||
|
extern my_bool bitmap_fast_test_and_set(MY_BITMAP *map, uint bitmap_bit);
|
||||||
extern uint bitmap_set_next(MY_BITMAP *map);
|
extern uint bitmap_set_next(MY_BITMAP *map);
|
||||||
extern uint bitmap_get_first(const MY_BITMAP *map);
|
extern uint bitmap_get_first(const MY_BITMAP *map);
|
||||||
extern uint bitmap_bits_set(const MY_BITMAP *map);
|
extern uint bitmap_bits_set(const MY_BITMAP *map);
|
||||||
|
@ -754,6 +754,8 @@ create view v1 as select * from t1;
|
|||||||
create view v2 as select * from t2;
|
create view v2 as select * from t2;
|
||||||
insert into v1 values (1);
|
insert into v1 values (1);
|
||||||
insert into v2 values (1);
|
insert into v2 values (1);
|
||||||
|
Warnings:
|
||||||
|
Warning 1423 Field of view 'test.v2' underlying table doesn't have a default value
|
||||||
create view v3 (a,b) as select v1.col1 as a, v2.col1 as b from v1, v2 where v1.col1 = v2.col1;
|
create view v3 (a,b) as select v1.col1 as a, v2.col1 as b from v1, v2 where v1.col1 = v2.col1;
|
||||||
select * from v3;
|
select * from v3;
|
||||||
a b
|
a b
|
||||||
@ -1850,3 +1852,16 @@ SELECT * FROM v1;
|
|||||||
SUBSTRING_INDEX("dkjhgd:kjhdjh", ":", 1)
|
SUBSTRING_INDEX("dkjhgd:kjhdjh", ":", 1)
|
||||||
dkjhgd
|
dkjhgd
|
||||||
drop view v1;
|
drop view v1;
|
||||||
|
set sql_mode='strict_all_tables';
|
||||||
|
CREATE TABLE t1 (col1 INT NOT NULL, col2 INT NOT NULL) ENGINE = INNODB;
|
||||||
|
CREATE VIEW v1 (vcol1) AS SELECT col1 FROM t1;
|
||||||
|
CREATE VIEW v2 (vcol1) AS SELECT col1 FROM t1 WHERE col2 > 2;
|
||||||
|
INSERT INTO t1 (col1) VALUES(12);
|
||||||
|
ERROR HY000: Field 'col2' doesn't have a default value
|
||||||
|
INSERT INTO v1 (vcol1) VALUES(12);
|
||||||
|
ERROR HY000: Field of view 'test.v1' underlying table doesn't have a default value
|
||||||
|
INSERT INTO v2 (vcol1) VALUES(12);
|
||||||
|
ERROR HY000: Field of view 'test.v2' underlying table doesn't have a default value
|
||||||
|
set sql_mode=default;
|
||||||
|
drop view v2,v1;
|
||||||
|
drop table t1;
|
||||||
|
@ -1696,3 +1696,21 @@ drop view v1;
|
|||||||
CREATE VIEW v1 AS SELECT SUBSTRING_INDEX("dkjhgd:kjhdjh", ":", 1);
|
CREATE VIEW v1 AS SELECT SUBSTRING_INDEX("dkjhgd:kjhdjh", ":", 1);
|
||||||
SELECT * FROM v1;
|
SELECT * FROM v1;
|
||||||
drop view v1;
|
drop view v1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Correct inserting data check (absence of default value) for view
|
||||||
|
# underlying tables (BUG#6443)
|
||||||
|
#
|
||||||
|
set sql_mode='strict_all_tables';
|
||||||
|
CREATE TABLE t1 (col1 INT NOT NULL, col2 INT NOT NULL) ENGINE = INNODB;
|
||||||
|
CREATE VIEW v1 (vcol1) AS SELECT col1 FROM t1;
|
||||||
|
CREATE VIEW v2 (vcol1) AS SELECT col1 FROM t1 WHERE col2 > 2;
|
||||||
|
-- error 1364
|
||||||
|
INSERT INTO t1 (col1) VALUES(12);
|
||||||
|
-- error 1423
|
||||||
|
INSERT INTO v1 (vcol1) VALUES(12);
|
||||||
|
-- error 1423
|
||||||
|
INSERT INTO v2 (vcol1) VALUES(12);
|
||||||
|
set sql_mode=default;
|
||||||
|
drop view v2,v1;
|
||||||
|
drop table t1;
|
||||||
|
@ -109,6 +109,51 @@ void bitmap_set_bit(MY_BITMAP *map, uint bitmap_bit)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
test if bit already set and set it if it was not (thread unsafe method)
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
bitmap_fast_test_and_set()
|
||||||
|
MAP bit map struct
|
||||||
|
BIT bit number
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
0 bit was not set
|
||||||
|
!=0 bit was set
|
||||||
|
*/
|
||||||
|
|
||||||
|
my_bool bitmap_fast_test_and_set(MY_BITMAP *map, uint bitmap_bit)
|
||||||
|
{
|
||||||
|
uchar *byte= map->bitmap + (bitmap_bit / 8);
|
||||||
|
uchar bit= 1 << ((bitmap_bit) & 7);
|
||||||
|
uchar res= (*byte) & bit;
|
||||||
|
*byte|= bit;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
test if bit already set and set it if it was not (thread safe method)
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
bitmap_fast_test_and_set()
|
||||||
|
map bit map struct
|
||||||
|
bitmap_bit bit number
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
0 bit was not set
|
||||||
|
!=0 bit was set
|
||||||
|
*/
|
||||||
|
|
||||||
|
my_bool bitmap_test_and_set(MY_BITMAP *map, uint bitmap_bit)
|
||||||
|
{
|
||||||
|
my_bool res;
|
||||||
|
DBUG_ASSERT(map->bitmap && bitmap_bit < map->bitmap_size*8);
|
||||||
|
bitmap_lock(map);
|
||||||
|
res= bitmap_fast_test_and_set(map, bitmap_bit);
|
||||||
|
bitmap_unlock(map);
|
||||||
|
}
|
||||||
|
|
||||||
uint bitmap_set_next(MY_BITMAP *map)
|
uint bitmap_set_next(MY_BITMAP *map)
|
||||||
{
|
{
|
||||||
uchar *bitmap=map->bitmap;
|
uchar *bitmap=map->bitmap;
|
||||||
|
@ -86,6 +86,7 @@ public:
|
|||||||
|
|
||||||
utype unireg_check;
|
utype unireg_check;
|
||||||
uint32 field_length; // Length of field
|
uint32 field_length; // Length of field
|
||||||
|
uint field_index; // field number in fields array
|
||||||
uint16 flags;
|
uint16 flags;
|
||||||
uchar null_bit; // Bit used to test null bit
|
uchar null_bit; // Bit used to test null bit
|
||||||
|
|
||||||
|
406
sql/item.cc
406
sql/item.cc
@ -440,16 +440,17 @@ void Item::rename(char *new_name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Item_ident::Item_ident(const char *db_name_par,const char *table_name_par,
|
Item_ident::Item_ident(Name_resolution_context *context_arg,
|
||||||
const char *field_name_par)
|
const char *db_name_arg,const char *table_name_arg,
|
||||||
:orig_db_name(db_name_par), orig_table_name(table_name_par),
|
const char *field_name_arg)
|
||||||
orig_field_name(field_name_par),
|
:orig_db_name(db_name_arg), orig_table_name(table_name_arg),
|
||||||
db_name(db_name_par), table_name(table_name_par),
|
orig_field_name(field_name_arg), context(context_arg),
|
||||||
field_name(field_name_par),
|
db_name(db_name_arg), table_name(table_name_arg),
|
||||||
|
field_name(field_name_arg),
|
||||||
alias_name_used(FALSE), cached_field_index(NO_CACHED_FIELD_INDEX),
|
alias_name_used(FALSE), cached_field_index(NO_CACHED_FIELD_INDEX),
|
||||||
cached_table(0), depended_from(0)
|
cached_table(0), depended_from(0)
|
||||||
{
|
{
|
||||||
name = (char*) field_name_par;
|
name = (char*) field_name_arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -460,6 +461,7 @@ Item_ident::Item_ident(THD *thd, Item_ident *item)
|
|||||||
orig_db_name(item->orig_db_name),
|
orig_db_name(item->orig_db_name),
|
||||||
orig_table_name(item->orig_table_name),
|
orig_table_name(item->orig_table_name),
|
||||||
orig_field_name(item->orig_field_name),
|
orig_field_name(item->orig_field_name),
|
||||||
|
context(item->context),
|
||||||
db_name(item->db_name),
|
db_name(item->db_name),
|
||||||
table_name(item->table_name),
|
table_name(item->table_name),
|
||||||
field_name(item->field_name),
|
field_name(item->field_name),
|
||||||
@ -785,7 +787,7 @@ Item_splocal::type() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Item_splocal::fix_fields(THD *, struct st_table_list *, Item **)
|
bool Item_splocal::fix_fields(THD *, Item **)
|
||||||
{
|
{
|
||||||
Item *it= this_item();
|
Item *it= this_item();
|
||||||
DBUG_ASSERT(it->fixed);
|
DBUG_ASSERT(it->fixed);
|
||||||
@ -855,7 +857,8 @@ void Item::split_sum_func2(THD *thd, Item **ref_pointer_array,
|
|||||||
uint el= fields.elements;
|
uint el= fields.elements;
|
||||||
Item *new_item;
|
Item *new_item;
|
||||||
ref_pointer_array[el]= this;
|
ref_pointer_array[el]= this;
|
||||||
if (!(new_item= new Item_ref(ref_pointer_array + el, 0, name)))
|
if (!(new_item= new Item_ref(&thd->lex->current_select->context,
|
||||||
|
ref_pointer_array + el, 0, name)))
|
||||||
return; // fatal_error is set
|
return; // fatal_error is set
|
||||||
fields.push_front(this);
|
fields.push_front(this);
|
||||||
ref_pointer_array[el]= this;
|
ref_pointer_array[el]= this;
|
||||||
@ -995,7 +998,7 @@ bool DTCollation::aggregate(DTCollation &dt, uint flags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Item_field::Item_field(Field *f)
|
Item_field::Item_field(Field *f)
|
||||||
:Item_ident(NullS, *f->table_name, f->field_name),
|
:Item_ident(0, NullS, *f->table_name, f->field_name),
|
||||||
item_equal(0), no_const_subst(0),
|
item_equal(0), no_const_subst(0),
|
||||||
have_privileges(0), any_privileges(0)
|
have_privileges(0), any_privileges(0)
|
||||||
{
|
{
|
||||||
@ -1007,8 +1010,9 @@ Item_field::Item_field(Field *f)
|
|||||||
orig_table_name= orig_field_name= "";
|
orig_table_name= orig_field_name= "";
|
||||||
}
|
}
|
||||||
|
|
||||||
Item_field::Item_field(THD *thd, Field *f)
|
Item_field::Item_field(THD *thd, Name_resolution_context *context_arg,
|
||||||
:Item_ident(f->table->s->db, *f->table_name, f->field_name),
|
Field *f)
|
||||||
|
:Item_ident(context_arg, f->table->s->db, *f->table_name, f->field_name),
|
||||||
item_equal(0), no_const_subst(0),
|
item_equal(0), no_const_subst(0),
|
||||||
have_privileges(0), any_privileges(0)
|
have_privileges(0), any_privileges(0)
|
||||||
{
|
{
|
||||||
@ -1043,6 +1047,17 @@ Item_field::Item_field(THD *thd, Field *f)
|
|||||||
set_field(f);
|
set_field(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Item_field::Item_field(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),
|
||||||
|
field(0), result_field(0), item_equal(0), no_const_subst(0),
|
||||||
|
have_privileges(0), any_privileges(0)
|
||||||
|
{
|
||||||
|
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::Item_field(THD *thd, Item_field *item)
|
Item_field::Item_field(THD *thd, Item_field *item)
|
||||||
:Item_ident(thd, item),
|
:Item_ident(thd, item),
|
||||||
@ -2233,7 +2248,7 @@ bool Item_param::convert_str_value(THD *thd)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Item_param::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
bool Item_param::fix_fields(THD *thd, Item **ref)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 0);
|
DBUG_ASSERT(fixed == 0);
|
||||||
SELECT_LEX *cursel= (SELECT_LEX *) thd->lex->current_select;
|
SELECT_LEX *cursel= (SELECT_LEX *) thd->lex->current_select;
|
||||||
@ -2393,9 +2408,7 @@ int Item_copy_string::save_in_field(Field *field, bool no_conversions)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* ARGSUSED */
|
/* ARGSUSED */
|
||||||
bool Item::fix_fields(THD *thd,
|
bool Item::fix_fields(THD *thd, Item ** ref)
|
||||||
struct st_table_list *list,
|
|
||||||
Item ** ref)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
// We do not check fields which are fixed during construction
|
// We do not check fields which are fixed during construction
|
||||||
@ -2762,7 +2775,6 @@ resolve_ref_in_select_and_group(THD *thd, Item_ident *ref, SELECT_LEX *select)
|
|||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
Item_field::fix_fields()
|
Item_field::fix_fields()
|
||||||
thd [in] current thread
|
thd [in] current thread
|
||||||
tables [in] the tables in a FROM clause
|
|
||||||
reference [in/out] view column if this item was resolved to a view column
|
reference [in/out] view column if this item was resolved to a view column
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
@ -2808,7 +2820,7 @@ resolve_ref_in_select_and_group(THD *thd, Item_ident *ref, SELECT_LEX *select)
|
|||||||
FALSE on success
|
FALSE on success
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
|
bool Item_field::fix_fields(THD *thd, Item **reference)
|
||||||
{
|
{
|
||||||
enum_parsing_place place= NO_MATTER;
|
enum_parsing_place place= NO_MATTER;
|
||||||
DBUG_ASSERT(fixed == 0);
|
DBUG_ASSERT(fixed == 0);
|
||||||
@ -2821,63 +2833,54 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
|
|||||||
expression to 'reference', i.e. it substitute that expression instead
|
expression to 'reference', i.e. it substitute that expression instead
|
||||||
of this Item_field
|
of this Item_field
|
||||||
*/
|
*/
|
||||||
if ((from_field= find_field_in_tables(thd, this, tables, reference,
|
if ((from_field= find_field_in_tables(thd, this, context->table_list,
|
||||||
|
reference,
|
||||||
IGNORE_EXCEPT_NON_UNIQUE,
|
IGNORE_EXCEPT_NON_UNIQUE,
|
||||||
!any_privileges)) ==
|
!any_privileges &&
|
||||||
|
context->check_privileges)) ==
|
||||||
not_found_field)
|
not_found_field)
|
||||||
{
|
{
|
||||||
SELECT_LEX *last= 0;
|
|
||||||
TABLE_LIST *table_list;
|
|
||||||
Item **ref= (Item **) not_found_item;
|
|
||||||
SELECT_LEX *current_sel= (SELECT_LEX *) thd->lex->current_select;
|
|
||||||
/*
|
/*
|
||||||
If there is an outer select, and it is not a derived table (which do
|
If there is an outer contexts (outer selects, but current select is
|
||||||
not support the use of outer fields for now), try to resolve this
|
not derived table or view) try to resolve this reference in the
|
||||||
reference in the outer select(s).
|
outer contexts.
|
||||||
|
|
||||||
We treat each subselect as a separate namespace, so that different
|
We treat each subselect as a separate namespace, so that different
|
||||||
subselects may contain columns with the same names. The subselects are
|
subselects may contain columns with the same names. The subselects are
|
||||||
searched starting from the innermost.
|
searched starting from the innermost.
|
||||||
*/
|
*/
|
||||||
if (current_sel->master_unit()->first_select()->linkage !=
|
Name_resolution_context *last_checked_context= context;
|
||||||
DERIVED_TABLE_TYPE)
|
Item **ref= (Item **) not_found_item;
|
||||||
|
Name_resolution_context *outer_context= context->outer_context;
|
||||||
|
for (;
|
||||||
|
outer_context;
|
||||||
|
outer_context= outer_context->outer_context)
|
||||||
{
|
{
|
||||||
SELECT_LEX_UNIT *prev_unit= current_sel->master_unit();
|
SELECT_LEX *select= outer_context->select_lex;
|
||||||
SELECT_LEX *outer_sel= prev_unit->outer_select();
|
Item_subselect *prev_subselect_item=
|
||||||
for ( ; outer_sel ;
|
last_checked_context->select_lex->master_unit()->item;
|
||||||
outer_sel= (prev_unit= outer_sel->master_unit())->outer_select())
|
last_checked_context= outer_context;
|
||||||
{
|
|
||||||
last= outer_sel;
|
|
||||||
Item_subselect *prev_subselect_item= prev_unit->item;
|
|
||||||
upward_lookup= TRUE;
|
upward_lookup= TRUE;
|
||||||
|
|
||||||
/* Search in the tables of the FROM clause of the outer select. */
|
|
||||||
table_list= outer_sel->get_table_list();
|
|
||||||
if (outer_sel->resolve_mode == SELECT_LEX::INSERT_MODE && table_list)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
It is a primary INSERT st_select_lex => do not resolve against the
|
|
||||||
first table.
|
|
||||||
*/
|
|
||||||
table_list= table_list->next_local;
|
|
||||||
}
|
|
||||||
place= prev_subselect_item->parsing_place;
|
place= prev_subselect_item->parsing_place;
|
||||||
/*
|
/*
|
||||||
Check table fields only if the subquery is used somewhere out of
|
Check table fields only if the subquery is used somewhere out of
|
||||||
HAVING, or the outer SELECT does not use grouping (i.e. tables are
|
HAVING, or the outer SELECT does not use grouping (i.e. tables are
|
||||||
accessible).
|
accessible).
|
||||||
|
|
||||||
In case of view, find_field_in_tables() write pointer to view
|
In case of a view, find_field_in_tables() writes the pointer to
|
||||||
field expression to 'reference', i.e. it substitute that
|
the found view field into '*reference', in other words, it
|
||||||
expression instead of this Item_field
|
substitutes this Item_field with the found expression.
|
||||||
*/
|
*/
|
||||||
if ((place != IN_HAVING ||
|
if ((place != IN_HAVING ||
|
||||||
(outer_sel->with_sum_func == 0 &&
|
(!select->with_sum_func &&
|
||||||
outer_sel->group_list.elements == 0)) &&
|
select->group_list.elements == 0)) &&
|
||||||
(from_field= find_field_in_tables(thd, this, table_list,
|
(from_field= find_field_in_tables(thd, this,
|
||||||
|
outer_context->table_list,
|
||||||
reference,
|
reference,
|
||||||
IGNORE_EXCEPT_NON_UNIQUE,
|
IGNORE_EXCEPT_NON_UNIQUE,
|
||||||
TRUE)) !=
|
outer_context->
|
||||||
|
check_privileges)) !=
|
||||||
not_found_field)
|
not_found_field)
|
||||||
{
|
{
|
||||||
if (from_field)
|
if (from_field)
|
||||||
@ -2894,14 +2897,16 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
|
|||||||
(*reference)->used_tables();
|
(*reference)->used_tables();
|
||||||
prev_subselect_item->const_item_cache&=
|
prev_subselect_item->const_item_cache&=
|
||||||
(*reference)->const_item();
|
(*reference)->const_item();
|
||||||
mark_as_dependent(thd, last, current_sel, this,
|
mark_as_dependent(thd, last_checked_context->select_lex,
|
||||||
|
context->select_lex, this,
|
||||||
((type == REF_ITEM || type == FIELD_ITEM) ?
|
((type == REF_ITEM || type == FIELD_ITEM) ?
|
||||||
(Item_ident*) (*reference) :
|
(Item_ident*) (*reference) :
|
||||||
0));
|
0));
|
||||||
/*
|
/*
|
||||||
view reference found, we substituted it instead of this
|
A reference to a view field had been found and we
|
||||||
Item (find_field_in_tables do it by assigning new value to
|
substituted it instead of this Item (find_field_in_tables
|
||||||
*reference), so can quit
|
does it by assigning the new value to *reference), so now
|
||||||
|
we can return from this function.
|
||||||
*/
|
*/
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@ -2909,11 +2914,11 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Search in the SELECT and GROUP lists of the outer select. */
|
/* Search in SELECT and GROUP lists of the outer select. */
|
||||||
if (outer_sel->resolve_mode == SELECT_LEX::SELECT_MODE)
|
if (outer_context->resolve_in_select_list)
|
||||||
{
|
{
|
||||||
if (!(ref= resolve_ref_in_select_and_group(thd, this, outer_sel)))
|
if (!(ref= resolve_ref_in_select_and_group(thd, this, select)))
|
||||||
return TRUE; /* Some error occurred (e.g. ambiguous names). */
|
goto error; /* Some error occurred (e.g. ambiguous names). */
|
||||||
if (ref != not_found_item)
|
if (ref != not_found_item)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(*ref && (*ref)->fixed);
|
DBUG_ASSERT(*ref && (*ref)->fixed);
|
||||||
@ -2923,19 +2928,18 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reference is not found => depend from outer (or just error)
|
/*
|
||||||
|
Reference is not found in this select => this subquery depend on
|
||||||
|
outer select (or we just trying to find wrong identifier, in this
|
||||||
|
case it does not matter which used tables bits we set)
|
||||||
|
*/
|
||||||
prev_subselect_item->used_tables_cache|= OUTER_REF_TABLE_BIT;
|
prev_subselect_item->used_tables_cache|= OUTER_REF_TABLE_BIT;
|
||||||
prev_subselect_item->const_item_cache= 0;
|
prev_subselect_item->const_item_cache= 0;
|
||||||
|
|
||||||
if (outer_sel->master_unit()->first_select()->linkage ==
|
|
||||||
DERIVED_TABLE_TYPE)
|
|
||||||
break; // do not look over derived table
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DBUG_ASSERT(ref != 0);
|
DBUG_ASSERT(ref != 0);
|
||||||
if (!from_field)
|
if (!from_field)
|
||||||
return TRUE;
|
goto error;
|
||||||
if (ref == not_found_item && from_field == not_found_field)
|
if (ref == not_found_item && from_field == not_found_field)
|
||||||
{
|
{
|
||||||
if (upward_lookup)
|
if (upward_lookup)
|
||||||
@ -2945,11 +2949,13 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Call to report error
|
/* Call find_field_in_tables only to report the error */
|
||||||
find_field_in_tables(thd, this, tables, reference, REPORT_ALL_ERRORS,
|
find_field_in_tables(thd, this, context->table_list,
|
||||||
TRUE);
|
reference, REPORT_ALL_ERRORS,
|
||||||
|
!any_privileges &&
|
||||||
|
context->check_privileges);
|
||||||
}
|
}
|
||||||
return TRUE;
|
goto error;
|
||||||
}
|
}
|
||||||
else if (ref != not_found_item)
|
else if (ref != not_found_item)
|
||||||
{
|
{
|
||||||
@ -2967,45 +2973,54 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
|
|||||||
save= *ref;
|
save= *ref;
|
||||||
*ref= NULL; // Don't call set_properties()
|
*ref= NULL; // Don't call set_properties()
|
||||||
rf= (place == IN_HAVING ?
|
rf= (place == IN_HAVING ?
|
||||||
new Item_ref(ref, (char*) table_name, (char*) field_name) :
|
new Item_ref(context, ref, (char*) table_name,
|
||||||
new Item_direct_ref(ref, (char*) table_name, (char*) field_name));
|
(char*) field_name) :
|
||||||
|
new Item_direct_ref(context, ref, (char*) table_name,
|
||||||
|
(char*) field_name));
|
||||||
*ref= save;
|
*ref= save;
|
||||||
if (!rf)
|
if (!rf)
|
||||||
return TRUE;
|
goto error;
|
||||||
thd->change_item_tree(reference, rf);
|
thd->change_item_tree(reference, rf);
|
||||||
/*
|
/*
|
||||||
rf is Item_ref => never substitute other items (in this case)
|
rf is Item_ref => never substitute other items (in this case)
|
||||||
during fix_fields() => we can use rf after fix_fields()
|
during fix_fields() => we can use rf after fix_fields()
|
||||||
*/
|
*/
|
||||||
DBUG_ASSERT(!rf->fixed); // Assured by Item_ref()
|
DBUG_ASSERT(!rf->fixed); // Assured by Item_ref()
|
||||||
if (rf->fix_fields(thd, tables, reference) || rf->check_cols(1))
|
if (rf->fix_fields(thd, reference) || rf->check_cols(1))
|
||||||
return TRUE;
|
goto error;
|
||||||
|
|
||||||
mark_as_dependent(thd, last, current_sel, this, rf);
|
mark_as_dependent(thd, last_checked_context->select_lex,
|
||||||
|
context->select_lex, this,
|
||||||
|
rf);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mark_as_dependent(thd, last, current_sel, this, this);
|
mark_as_dependent(thd, last_checked_context->select_lex,
|
||||||
if (last->having_fix_field)
|
context->select_lex,
|
||||||
|
this, this);
|
||||||
|
if (last_checked_context->select_lex->having_fix_field)
|
||||||
{
|
{
|
||||||
Item_ref *rf;
|
Item_ref *rf;
|
||||||
rf= new Item_ref((cached_table->db[0] ? cached_table->db : 0),
|
rf= new Item_ref(context,
|
||||||
|
(cached_table->db[0] ? cached_table->db : 0),
|
||||||
(char*) cached_table->alias, (char*) field_name);
|
(char*) cached_table->alias, (char*) field_name);
|
||||||
if (!rf)
|
if (!rf)
|
||||||
return TRUE;
|
goto error;
|
||||||
thd->change_item_tree(reference, rf);
|
thd->change_item_tree(reference, rf);
|
||||||
/*
|
/*
|
||||||
rf is Item_ref => never substitute other items (in this case)
|
rf is Item_ref => never substitute other items (in this case)
|
||||||
during fix_fields() => we can use rf after fix_fields()
|
during fix_fields() => we can use rf after fix_fields()
|
||||||
*/
|
*/
|
||||||
DBUG_ASSERT(!rf->fixed); // Assured by Item_ref()
|
DBUG_ASSERT(!rf->fixed); // Assured by Item_ref()
|
||||||
return (rf->fix_fields(thd, tables, reference) || rf->check_cols(1));
|
if (rf->fix_fields(thd, reference) || rf->check_cols(1))
|
||||||
|
goto error;
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!from_field)
|
else if (!from_field)
|
||||||
return TRUE;
|
goto error;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if it is not expression from merged VIEW we will set this field.
|
if it is not expression from merged VIEW we will set this field.
|
||||||
@ -3053,12 +3068,16 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
|
|||||||
my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0),
|
my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0),
|
||||||
"ANY", thd->priv_user, thd->host_or_ip,
|
"ANY", thd->priv_user, thd->host_or_ip,
|
||||||
field_name, tab);
|
field_name, tab);
|
||||||
return TRUE;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
fixed= 1;
|
fixed= 1;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
error:
|
||||||
|
context->process_error(thd);
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3922,16 +3941,17 @@ bool Item_field::send(Protocol *protocol, String *buffer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Item_ref::Item_ref(Item **item, const char *table_name_par,
|
Item_ref::Item_ref(Name_resolution_context *context_arg,
|
||||||
const char *field_name_par)
|
Item **item, const char *table_name_arg,
|
||||||
:Item_ident(NullS, table_name_par, field_name_par), result_field(0),
|
const char *field_name_arg)
|
||||||
ref(item)
|
:Item_ident(context_arg, NullS, table_name_arg, field_name_arg),
|
||||||
|
result_field(0), ref(item)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
This constructor used to create some internals references over fixed items
|
This constructor used to create some internals references over fixed items
|
||||||
*/
|
*/
|
||||||
DBUG_ASSERT(ref != 0);
|
DBUG_ASSERT(ref != 0);
|
||||||
if (*ref)
|
if (*ref && (*ref)->fixed)
|
||||||
set_properties();
|
set_properties();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3942,7 +3962,6 @@ Item_ref::Item_ref(Item **item, const char *table_name_par,
|
|||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
Item_ref::fix_fields()
|
Item_ref::fix_fields()
|
||||||
thd [in] current thread
|
thd [in] current thread
|
||||||
tables [in] the tables in a FROM clause
|
|
||||||
reference [in/out] view column if this item was resolved to a view column
|
reference [in/out] view column if this item was resolved to a view column
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
@ -3994,59 +4013,56 @@ Item_ref::Item_ref(Item **item, const char *table_name_par,
|
|||||||
FALSE on success
|
FALSE on success
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool Item_ref::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
|
bool Item_ref::fix_fields(THD *thd, Item **reference)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 0);
|
|
||||||
enum_parsing_place place= NO_MATTER;
|
enum_parsing_place place= NO_MATTER;
|
||||||
|
DBUG_ASSERT(fixed == 0);
|
||||||
SELECT_LEX *current_sel= thd->lex->current_select;
|
SELECT_LEX *current_sel= thd->lex->current_select;
|
||||||
|
|
||||||
if (!ref || ref == not_found_item)
|
if (!ref || ref == not_found_item)
|
||||||
{
|
{
|
||||||
SELECT_LEX_UNIT *prev_unit= current_sel->master_unit();
|
if (!(ref= resolve_ref_in_select_and_group(thd, this,
|
||||||
SELECT_LEX *outer_sel= prev_unit->outer_select();
|
context->select_lex)))
|
||||||
|
goto error; /* Some error occurred (e.g. ambiguous names). */
|
||||||
if (!(ref= resolve_ref_in_select_and_group(thd, this, current_sel)))
|
|
||||||
return TRUE; /* Some error occurred (e.g. ambiguous names). */
|
|
||||||
|
|
||||||
if (ref == not_found_item) /* This reference was not resolved. */
|
if (ref == not_found_item) /* This reference was not resolved. */
|
||||||
{
|
{
|
||||||
TABLE_LIST *table_list;
|
Name_resolution_context *last_checked_context= context;
|
||||||
|
Name_resolution_context *outer_context= context->outer_context;
|
||||||
Field *from_field;
|
Field *from_field;
|
||||||
SELECT_LEX *last;
|
|
||||||
ref= 0;
|
ref= 0;
|
||||||
|
|
||||||
if (!outer_sel || (current_sel->master_unit()->first_select()->linkage ==
|
if (!outer_context)
|
||||||
DERIVED_TABLE_TYPE))
|
|
||||||
{
|
{
|
||||||
/* The current reference cannot be resolved in this query. */
|
/* The current reference cannot be resolved in this query. */
|
||||||
my_error(ER_BAD_FIELD_ERROR,MYF(0),
|
my_error(ER_BAD_FIELD_ERROR,MYF(0),
|
||||||
this->full_name(), current_thd->where);
|
this->full_name(), current_thd->where);
|
||||||
return TRUE;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
If there is an outer select, and it is not a derived table (which do
|
If there is an outer context (select), and it is not a derived table
|
||||||
not support the use of outer fields for now), try to resolve this
|
(which do not support the use of outer fields for now), try to
|
||||||
reference in the outer select(s).
|
resolve this reference in the outer select(s).
|
||||||
|
|
||||||
We treat each subselect as a separate namespace, so that different
|
We treat each subselect as a separate namespace, so that different
|
||||||
subselects may contain columns with the same names. The subselects are
|
subselects may contain columns with the same names. The subselects are
|
||||||
searched starting from the innermost.
|
searched starting from the innermost.
|
||||||
*/
|
*/
|
||||||
from_field= (Field*) not_found_field;
|
from_field= (Field*) not_found_field;
|
||||||
last= 0;
|
|
||||||
|
|
||||||
/* The following loop will always be excuted at least once */
|
do
|
||||||
for ( ; outer_sel ;
|
|
||||||
outer_sel= (prev_unit= outer_sel->master_unit())->outer_select())
|
|
||||||
{
|
{
|
||||||
last= outer_sel;
|
SELECT_LEX *select= outer_context->select_lex;
|
||||||
Item_subselect *prev_subselect_item= prev_unit->item;
|
Item_subselect *prev_subselect_item=
|
||||||
|
last_checked_context->select_lex->master_unit()->item;
|
||||||
|
last_checked_context= outer_context;
|
||||||
|
|
||||||
/* Search in the SELECT and GROUP lists of the outer select. */
|
/* Search in the SELECT and GROUP lists of the outer select. */
|
||||||
if (outer_sel->resolve_mode == SELECT_LEX::SELECT_MODE)
|
if (outer_context->resolve_in_select_list)
|
||||||
{
|
{
|
||||||
if (!(ref= resolve_ref_in_select_and_group(thd, this, outer_sel)))
|
if (!(ref= resolve_ref_in_select_and_group(thd, this, select)))
|
||||||
return TRUE; /* Some error occurred (e.g. ambiguous names). */
|
goto error; /* Some error occurred (e.g. ambiguous names). */
|
||||||
if (ref != not_found_item)
|
if (ref != not_found_item)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(*ref && (*ref)->fixed);
|
DBUG_ASSERT(*ref && (*ref)->fixed);
|
||||||
@ -4062,17 +4078,6 @@ bool Item_ref::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
|
|||||||
ref= 0;
|
ref= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Search in the tables of the FROM clause of the outer select. */
|
|
||||||
table_list= outer_sel->get_table_list();
|
|
||||||
if (outer_sel->resolve_mode == SELECT_LEX::INSERT_MODE && table_list)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
It is a primary INSERT st_select_lex => do not resolve against
|
|
||||||
the first table.
|
|
||||||
*/
|
|
||||||
table_list= table_list->next_local;
|
|
||||||
}
|
|
||||||
|
|
||||||
place= prev_subselect_item->parsing_place;
|
place= prev_subselect_item->parsing_place;
|
||||||
/*
|
/*
|
||||||
Check table fields only if the subquery is used somewhere out of
|
Check table fields only if the subquery is used somewhere out of
|
||||||
@ -4085,20 +4090,21 @@ bool Item_ref::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
|
|||||||
ER_BAD_FIELD_ERROR which we produce now.
|
ER_BAD_FIELD_ERROR which we produce now.
|
||||||
*/
|
*/
|
||||||
if ((place != IN_HAVING ||
|
if ((place != IN_HAVING ||
|
||||||
(!outer_sel->with_sum_func &&
|
(!select->with_sum_func &&
|
||||||
outer_sel->group_list.elements == 0)))
|
select->group_list.elements == 0)))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
In case of view, find_field_in_tables() write pointer to view
|
In case of view, find_field_in_tables() write pointer to view
|
||||||
field expression to 'reference', i.e. it substitute that
|
field expression to 'reference', i.e. it substitute that
|
||||||
expression instead of this Item_ref
|
expression instead of this Item_ref
|
||||||
*/
|
*/
|
||||||
from_field= find_field_in_tables(thd, this, table_list,
|
from_field= find_field_in_tables(thd, this,
|
||||||
|
outer_context->table_list,
|
||||||
reference,
|
reference,
|
||||||
IGNORE_EXCEPT_NON_UNIQUE,
|
IGNORE_EXCEPT_NON_UNIQUE,
|
||||||
TRUE);
|
outer_context->check_privileges);
|
||||||
if (! from_field)
|
if (! from_field)
|
||||||
return TRUE;
|
goto error;
|
||||||
if (from_field == view_ref_found)
|
if (from_field == view_ref_found)
|
||||||
{
|
{
|
||||||
Item::Type type= (*reference)->type();
|
Item::Type type= (*reference)->type();
|
||||||
@ -4107,7 +4113,8 @@ bool Item_ref::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
|
|||||||
prev_subselect_item->const_item_cache&=
|
prev_subselect_item->const_item_cache&=
|
||||||
(*reference)->const_item();
|
(*reference)->const_item();
|
||||||
DBUG_ASSERT((*reference)->type() == REF_ITEM);
|
DBUG_ASSERT((*reference)->type() == REF_ITEM);
|
||||||
mark_as_dependent(thd, last, current_sel, this,
|
mark_as_dependent(thd, last_checked_context->select_lex,
|
||||||
|
context->select_lex, this,
|
||||||
((type == REF_ITEM || type == FIELD_ITEM) ?
|
((type == REF_ITEM || type == FIELD_ITEM) ?
|
||||||
(Item_ident*) (*reference) :
|
(Item_ident*) (*reference) :
|
||||||
0));
|
0));
|
||||||
@ -4130,19 +4137,18 @@ bool Item_ref::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
|
|||||||
prev_subselect_item->used_tables_cache|= OUTER_REF_TABLE_BIT;
|
prev_subselect_item->used_tables_cache|= OUTER_REF_TABLE_BIT;
|
||||||
prev_subselect_item->const_item_cache= 0;
|
prev_subselect_item->const_item_cache= 0;
|
||||||
|
|
||||||
if (outer_sel->master_unit()->first_select()->linkage ==
|
outer_context= outer_context->outer_context;
|
||||||
DERIVED_TABLE_TYPE)
|
} while (outer_context);
|
||||||
break; /* Do not consider derived tables. */
|
|
||||||
}
|
|
||||||
|
|
||||||
DBUG_ASSERT(from_field != 0 && from_field != view_ref_found);
|
DBUG_ASSERT(from_field != 0 && from_field != view_ref_found);
|
||||||
if (from_field != not_found_field)
|
if (from_field != not_found_field)
|
||||||
{
|
{
|
||||||
Item_field* fld;
|
Item_field* fld;
|
||||||
if (!(fld= new Item_field(from_field)))
|
if (!(fld= new Item_field(from_field)))
|
||||||
return TRUE;
|
goto error;
|
||||||
thd->change_item_tree(reference, fld);
|
thd->change_item_tree(reference, fld);
|
||||||
mark_as_dependent(thd, last, thd->lex->current_select, this, fld);
|
mark_as_dependent(thd, last_checked_context->select_lex,
|
||||||
|
thd->lex->current_select, this, fld);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if (ref == 0)
|
if (ref == 0)
|
||||||
@ -4150,11 +4156,12 @@ bool Item_ref::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
|
|||||||
/* The item was not a table field and not a reference */
|
/* The item was not a table field and not a reference */
|
||||||
my_error(ER_BAD_FIELD_ERROR, MYF(0),
|
my_error(ER_BAD_FIELD_ERROR, MYF(0),
|
||||||
this->full_name(), current_thd->where);
|
this->full_name(), current_thd->where);
|
||||||
return TRUE;
|
goto error;
|
||||||
}
|
}
|
||||||
/* Should be checked in resolve_ref_in_select_and_group(). */
|
/* Should be checked in resolve_ref_in_select_and_group(). */
|
||||||
DBUG_ASSERT(*ref && (*ref)->fixed);
|
DBUG_ASSERT(*ref && (*ref)->fixed);
|
||||||
mark_as_dependent(thd, last, current_sel, this, this);
|
mark_as_dependent(thd, last_checked_context->select_lex,
|
||||||
|
context->select_lex, this, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4174,14 +4181,18 @@ bool Item_ref::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
|
|||||||
name, ((*ref)->with_sum_func?
|
name, ((*ref)->with_sum_func?
|
||||||
"reference to group function":
|
"reference to group function":
|
||||||
"forward reference in item list"));
|
"forward reference in item list"));
|
||||||
return TRUE;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_properties();
|
set_properties();
|
||||||
|
|
||||||
if ((*ref)->check_cols(1))
|
if ((*ref)->check_cols(1))
|
||||||
return TRUE;
|
goto error;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
error:
|
||||||
|
context->process_error(thd);
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -4389,6 +4400,19 @@ int Item_ref::save_in_field(Field *to, bool no_conversions)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Item_ref::make_field(Send_field *field)
|
||||||
|
{
|
||||||
|
(*ref)->make_field(field);
|
||||||
|
/* Non-zero in case of a view */
|
||||||
|
if (name)
|
||||||
|
field->col_name= name;
|
||||||
|
if (table_name)
|
||||||
|
field->table_name= table_name;
|
||||||
|
if (db_name)
|
||||||
|
field->db_name= db_name;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
void Item_ref_null_helper::print(String *str)
|
void Item_ref_null_helper::print(String *str)
|
||||||
{
|
{
|
||||||
str->append("<ref_null_helper>(", 18);
|
str->append("<ref_null_helper>(", 18);
|
||||||
@ -4452,6 +4476,31 @@ bool Item_direct_ref::get_date(TIME *ltime,uint fuzzydate)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Prepare referenced view viewld then call usual Item_direct_ref::fix_fields
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
Item_direct_view_ref::fix_fields()
|
||||||
|
thd thread handler
|
||||||
|
reference reference on reference where this item stored
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
FALSE OK
|
||||||
|
TRUE Error
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool Item_direct_view_ref::fix_fields(THD *thd, Item **reference)
|
||||||
|
{
|
||||||
|
/* view fild reference must be defined */
|
||||||
|
DBUG_ASSERT(*ref);
|
||||||
|
/* (*ref)->check_cols() will be made in Item_direct_ref::fix_fields */
|
||||||
|
if (!(*ref)->fixed &&
|
||||||
|
((*ref)->fix_fields(thd, ref)))
|
||||||
|
return TRUE;
|
||||||
|
return Item_direct_ref::fix_fields(thd, reference);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Item_null_helper::print(String *str)
|
void Item_null_helper::print(String *str)
|
||||||
{
|
{
|
||||||
str->append("<null_helper>(", 14);
|
str->append("<null_helper>(", 14);
|
||||||
@ -4467,9 +4516,7 @@ bool Item_default_value::eq(const Item *item, bool binary_cmp) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Item_default_value::fix_fields(THD *thd,
|
bool Item_default_value::fix_fields(THD *thd, Item **items)
|
||||||
struct st_table_list *table_list,
|
|
||||||
Item **items)
|
|
||||||
{
|
{
|
||||||
Item *real_arg;
|
Item *real_arg;
|
||||||
Item_field *field_arg;
|
Item_field *field_arg;
|
||||||
@ -4481,29 +4528,34 @@ bool Item_default_value::fix_fields(THD *thd,
|
|||||||
fixed= 1;
|
fixed= 1;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if (!arg->fixed && arg->fix_fields(thd, table_list, &arg))
|
if (!arg->fixed && arg->fix_fields(thd, &arg))
|
||||||
return TRUE;
|
goto error;
|
||||||
|
|
||||||
|
|
||||||
real_arg= arg->real_item();
|
real_arg= arg->real_item();
|
||||||
if (real_arg->type() != FIELD_ITEM)
|
if (real_arg->type() != FIELD_ITEM)
|
||||||
{
|
{
|
||||||
my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), arg->name);
|
my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), arg->name);
|
||||||
return TRUE;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
field_arg= (Item_field *)real_arg;
|
field_arg= (Item_field *)real_arg;
|
||||||
if (field_arg->field->flags & NO_DEFAULT_VALUE_FLAG)
|
if (field_arg->field->flags & NO_DEFAULT_VALUE_FLAG)
|
||||||
{
|
{
|
||||||
my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), field_arg->field->field_name);
|
my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), field_arg->field->field_name);
|
||||||
return TRUE;
|
goto error;
|
||||||
}
|
}
|
||||||
if (!(def_field= (Field*) sql_alloc(field_arg->field->size_of())))
|
if (!(def_field= (Field*) sql_alloc(field_arg->field->size_of())))
|
||||||
return TRUE;
|
goto error;
|
||||||
memcpy(def_field, field_arg->field, field_arg->field->size_of());
|
memcpy(def_field, field_arg->field, field_arg->field->size_of());
|
||||||
def_field->move_field(def_field->table->s->default_values -
|
def_field->move_field(def_field->table->s->default_values -
|
||||||
def_field->table->record[0]);
|
def_field->table->record[0]);
|
||||||
set_field(def_field);
|
set_field(def_field);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
error:
|
||||||
|
context->process_error(thd);
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -4525,12 +4577,28 @@ int Item_default_value::save_in_field(Field *field_arg, bool no_conversions)
|
|||||||
if (!arg)
|
if (!arg)
|
||||||
{
|
{
|
||||||
if (field_arg->flags & NO_DEFAULT_VALUE_FLAG)
|
if (field_arg->flags & NO_DEFAULT_VALUE_FLAG)
|
||||||
|
{
|
||||||
|
if (context->error_processor == &view_error_processor)
|
||||||
|
{
|
||||||
|
TABLE_LIST *view= (cached_table->belong_to_view ?
|
||||||
|
cached_table->belong_to_view :
|
||||||
|
cached_table);
|
||||||
|
// TODO: make correct error message
|
||||||
|
push_warning_printf(field_arg->table->in_use,
|
||||||
|
MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||||
|
ER_NO_DEFAULT_FOR_VIEW_FIELD,
|
||||||
|
ER(ER_NO_DEFAULT_FOR_VIEW_FIELD),
|
||||||
|
view->view_db.str,
|
||||||
|
view->view_name.str);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
push_warning_printf(field_arg->table->in_use,
|
push_warning_printf(field_arg->table->in_use,
|
||||||
MYSQL_ERROR::WARN_LEVEL_WARN,
|
MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||||
ER_NO_DEFAULT_FOR_FIELD,
|
ER_NO_DEFAULT_FOR_FIELD,
|
||||||
ER(ER_NO_DEFAULT_FOR_FIELD),
|
ER(ER_NO_DEFAULT_FOR_FIELD),
|
||||||
field_arg->field_name);
|
field_arg->field_name);
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
field_arg->set_default();
|
field_arg->set_default();
|
||||||
@ -4547,12 +4615,10 @@ bool Item_insert_value::eq(const Item *item, bool binary_cmp) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Item_insert_value::fix_fields(THD *thd,
|
bool Item_insert_value::fix_fields(THD *thd, Item **items)
|
||||||
struct st_table_list *table_list,
|
|
||||||
Item **items)
|
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 0);
|
DBUG_ASSERT(fixed == 0);
|
||||||
if (!arg->fixed && arg->fix_fields(thd, table_list, &arg))
|
if (!arg->fixed && arg->fix_fields(thd, &arg))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
if (arg->type() == REF_ITEM)
|
if (arg->type() == REF_ITEM)
|
||||||
@ -4641,9 +4707,7 @@ bool Item_trigger_field::eq(const Item *item, bool binary_cmp) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Item_trigger_field::fix_fields(THD *thd,
|
bool Item_trigger_field::fix_fields(THD *thd, Item **items)
|
||||||
TABLE_LIST *table_list,
|
|
||||||
Item **items)
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Since trigger is object tightly associated with TABLE object most
|
Since trigger is object tightly associated with TABLE object most
|
||||||
@ -5411,6 +5475,34 @@ void Item_result_field::cleanup()
|
|||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Dummy error processor used by default by Name_resolution_context
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
dummy_error_processor()
|
||||||
|
|
||||||
|
NOTE
|
||||||
|
do nothing
|
||||||
|
*/
|
||||||
|
|
||||||
|
void dummy_error_processor(THD *thd, void *data)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Wrapper of hide_view_error call for Name_resolution_context error processor
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
view_error_processor()
|
||||||
|
|
||||||
|
NOTE
|
||||||
|
hide view underlying tables details in error messages
|
||||||
|
*/
|
||||||
|
|
||||||
|
void view_error_processor(THD *thd, void *data)
|
||||||
|
{
|
||||||
|
((TABLE_LIST *)data)->hide_view_error(thd);
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
** Instantiate templates
|
** Instantiate templates
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
227
sql/item.h
227
sql/item.h
@ -24,7 +24,6 @@ struct st_table_list;
|
|||||||
void item_init(void); /* Init item functions */
|
void item_init(void); /* Init item functions */
|
||||||
class Item_field;
|
class Item_field;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
"Declared Type Collation"
|
"Declared Type Collation"
|
||||||
A combination of collation and its derivation.
|
A combination of collation and its derivation.
|
||||||
@ -218,6 +217,97 @@ struct Hybrid_type_traits_integer: public Hybrid_type_traits
|
|||||||
static const Hybrid_type_traits_integer *instance();
|
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 bool (Item::*Item_processor)(byte *arg);
|
||||||
@ -234,7 +324,8 @@ class Item {
|
|||||||
Item(const Item &); /* Prevent use of these */
|
Item(const Item &); /* Prevent use of these */
|
||||||
void operator=(Item &);
|
void operator=(Item &);
|
||||||
public:
|
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)
|
static void *operator new(size_t size, MEM_ROOT *mem_root)
|
||||||
{ return (void*) alloc_root(mem_root, (uint) size); }
|
{ return (void*) alloc_root(mem_root, (uint) size); }
|
||||||
/* Special for SP local variable assignment - reusing slots */
|
/* Special for SP local variable assignment - reusing slots */
|
||||||
@ -248,7 +339,8 @@ public:
|
|||||||
PROC_ITEM,COND_ITEM, REF_ITEM, FIELD_STD_ITEM,
|
PROC_ITEM,COND_ITEM, REF_ITEM, FIELD_STD_ITEM,
|
||||||
FIELD_VARIANCE_ITEM, INSERT_VALUE_ITEM,
|
FIELD_VARIANCE_ITEM, INSERT_VALUE_ITEM,
|
||||||
SUBSELECT_ITEM, ROW_ITEM, CACHE_ITEM, TYPE_HOLDER,
|
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 };
|
enum cond_result { COND_UNDEF,COND_OK,COND_TRUE,COND_FALSE };
|
||||||
|
|
||||||
@ -302,7 +394,7 @@ public:
|
|||||||
virtual void cleanup();
|
virtual void cleanup();
|
||||||
virtual void make_field(Send_field *field);
|
virtual void make_field(Send_field *field);
|
||||||
Field *make_string_field(TABLE *table);
|
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
|
should be used in case where we are sure that we do not need
|
||||||
complete fix_fields() procedure.
|
complete fix_fields() procedure.
|
||||||
@ -554,6 +646,8 @@ public:
|
|||||||
virtual bool remove_fixed(byte * arg) { fixed= 0; return 0; }
|
virtual bool remove_fixed(byte * arg) { fixed= 0; return 0; }
|
||||||
virtual bool cleanup_processor(byte *arg);
|
virtual bool cleanup_processor(byte *arg);
|
||||||
virtual bool collect_item_field_processor(byte * arg) { return 0; }
|
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 *equal_fields_propagator(byte * arg) { return this; }
|
||||||
virtual Item *set_no_const_sub(byte *arg) { return this; }
|
virtual Item *set_no_const_sub(byte *arg) { return this; }
|
||||||
virtual Item *replace_equal_field(byte * arg) { return this; }
|
virtual Item *replace_equal_field(byte * arg) { return this; }
|
||||||
@ -631,7 +725,7 @@ public:
|
|||||||
Item **this_item_addr(THD *thd, Item **);
|
Item **this_item_addr(THD *thd, Item **);
|
||||||
Item *this_const_item() const;
|
Item *this_const_item() const;
|
||||||
|
|
||||||
bool fix_fields(THD *, struct st_table_list *, Item **);
|
bool fix_fields(THD *, Item **);
|
||||||
void cleanup();
|
void cleanup();
|
||||||
|
|
||||||
inline uint get_offset()
|
inline uint get_offset()
|
||||||
@ -704,7 +798,9 @@ protected:
|
|||||||
const char *orig_db_name;
|
const char *orig_db_name;
|
||||||
const char *orig_table_name;
|
const char *orig_table_name;
|
||||||
const char *orig_field_name;
|
const char *orig_field_name;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
Name_resolution_context *context;
|
||||||
const char *db_name;
|
const char *db_name;
|
||||||
const char *table_name;
|
const char *table_name;
|
||||||
const char *field_name;
|
const char *field_name;
|
||||||
@ -722,13 +818,16 @@ public:
|
|||||||
*/
|
*/
|
||||||
TABLE_LIST *cached_table;
|
TABLE_LIST *cached_table;
|
||||||
st_select_lex *depended_from;
|
st_select_lex *depended_from;
|
||||||
Item_ident(const char *db_name_par,const char *table_name_par,
|
Item_ident(Name_resolution_context *context_arg,
|
||||||
const char *field_name_par);
|
const char *db_name_arg, const char *table_name_arg,
|
||||||
|
const char *field_name_arg);
|
||||||
Item_ident(THD *thd, Item_ident *item);
|
Item_ident(THD *thd, Item_ident *item);
|
||||||
const char *full_name() const;
|
const char *full_name() const;
|
||||||
void cleanup();
|
void cleanup();
|
||||||
bool remove_dependence_processor(byte * arg);
|
bool remove_dependence_processor(byte * arg);
|
||||||
void print(String *str);
|
void print(String *str);
|
||||||
|
virtual bool change_context_processor(byte *cntx)
|
||||||
|
{ context= (Name_resolution_context *)cntx; return FALSE; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class Item_equal;
|
class Item_equal;
|
||||||
@ -750,12 +849,9 @@ public:
|
|||||||
/* field need any privileges (for VIEW creation) */
|
/* field need any privileges (for VIEW creation) */
|
||||||
bool any_privileges;
|
bool any_privileges;
|
||||||
|
|
||||||
Item_field(const char *db_par,const char *table_name_par,
|
Item_field(Name_resolution_context *context_arg,
|
||||||
const char *field_name_par)
|
const char *db_arg,const char *table_name_arg,
|
||||||
:Item_ident(db_par,table_name_par,field_name_par),
|
const char *field_name_arg);
|
||||||
field(0), result_field(0), item_equal(0), no_const_subst(0),
|
|
||||||
have_privileges(0), any_privileges(0)
|
|
||||||
{ collation.set(DERIVATION_IMPLICIT); }
|
|
||||||
/*
|
/*
|
||||||
Constructor needed to process subselect with temporary tables (see Item)
|
Constructor needed to process subselect with temporary tables (see Item)
|
||||||
*/
|
*/
|
||||||
@ -765,7 +861,7 @@ public:
|
|||||||
and database names will live as long as Item_field (this is important
|
and database names will live as long as Item_field (this is important
|
||||||
in prepared statements).
|
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
|
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
|
db_name, table_name and column_name are unknown. It's necessary to call
|
||||||
@ -785,7 +881,7 @@ public:
|
|||||||
bool val_bool_result();
|
bool val_bool_result();
|
||||||
bool send(Protocol *protocol, String *str_arg);
|
bool send(Protocol *protocol, String *str_arg);
|
||||||
void reset_field(Field *f);
|
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);
|
void make_field(Send_field *tmp_field);
|
||||||
int save_in_field(Field *field,bool no_conversions);
|
int save_in_field(Field *field,bool no_conversions);
|
||||||
void save_org_in_field(Field *field);
|
void save_org_in_field(Field *field);
|
||||||
@ -946,7 +1042,7 @@ public:
|
|||||||
bool get_time(TIME *tm);
|
bool get_time(TIME *tm);
|
||||||
bool get_date(TIME *tm, uint fuzzydate);
|
bool get_date(TIME *tm, uint fuzzydate);
|
||||||
int save_in_field(Field *field, bool no_conversions);
|
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_null();
|
||||||
void set_int(longlong i, uint32 max_length_arg);
|
void set_int(longlong i, uint32 max_length_arg);
|
||||||
@ -1317,9 +1413,11 @@ protected:
|
|||||||
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_ref(Name_resolution_context *context_arg,
|
||||||
const char *field_name_par)
|
const char *db_arg, const char *table_name_arg,
|
||||||
:Item_ident(db_par, table_name_par, field_name_par), result_field(0), ref(0) {}
|
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:
|
This constructor is used in two scenarios:
|
||||||
A) *item = NULL
|
A) *item = NULL
|
||||||
@ -1334,10 +1432,12 @@ public:
|
|||||||
TODO we probably fix a superset of problems like in BUG#6658. Check this
|
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.
|
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) */
|
/* 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; }
|
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); }
|
||||||
@ -1354,8 +1454,8 @@ public:
|
|||||||
my_decimal *val_decimal_result(my_decimal *);
|
my_decimal *val_decimal_result(my_decimal *);
|
||||||
bool val_bool_result();
|
bool val_bool_result();
|
||||||
bool send(Protocol *prot, String *tmp);
|
bool send(Protocol *prot, String *tmp);
|
||||||
void make_field(Send_field *field) { (*ref)->make_field(field); }
|
void make_field(Send_field *field);
|
||||||
bool fix_fields(THD *, struct st_table_list *, Item **);
|
bool fix_fields(THD *, Item **);
|
||||||
int save_in_field(Field *field, bool no_conversions);
|
int save_in_field(Field *field, bool no_conversions);
|
||||||
void save_org_in_field(Field *field) { (*ref)->save_org_in_field(field); }
|
void save_org_in_field(Field *field) { (*ref)->save_org_in_field(field); }
|
||||||
enum Item_result result_type () const { return (*ref)->result_type(); }
|
enum Item_result result_type () const { return (*ref)->result_type(); }
|
||||||
@ -1380,6 +1480,8 @@ public:
|
|||||||
{ return (*ref)->walk(processor, arg); }
|
{ return (*ref)->walk(processor, arg); }
|
||||||
void print(String *str);
|
void print(String *str);
|
||||||
void cleanup();
|
void cleanup();
|
||||||
|
Item_field *filed_for_view_update()
|
||||||
|
{ return (*ref)->filed_for_view_update(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -1390,9 +1492,10 @@ public:
|
|||||||
class Item_direct_ref :public Item_ref
|
class Item_direct_ref :public Item_ref
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Item_direct_ref(Item **item, const char *table_name_par,
|
Item_direct_ref(Name_resolution_context *context_arg, Item **item,
|
||||||
const char *field_name_par)
|
const char *table_name_arg,
|
||||||
:Item_ref(item, table_name_par, field_name_par) {}
|
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) */
|
/* Constructor need to process subselect with temporary tables (see Item) */
|
||||||
Item_direct_ref(THD *thd, Item_direct_ref *item) : Item_ref(thd, item) {}
|
Item_direct_ref(THD *thd, Item_direct_ref *item) : Item_ref(thd, item) {}
|
||||||
|
|
||||||
@ -1405,6 +1508,24 @@ public:
|
|||||||
bool get_date(TIME *ltime,uint fuzzydate);
|
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;
|
class Item_in_subselect;
|
||||||
|
|
||||||
@ -1413,9 +1534,11 @@ class Item_ref_null_helper: public Item_ref
|
|||||||
protected:
|
protected:
|
||||||
Item_in_subselect* owner;
|
Item_in_subselect* owner;
|
||||||
public:
|
public:
|
||||||
Item_ref_null_helper(Item_in_subselect* master, Item **item,
|
Item_ref_null_helper(Name_resolution_context *context_arg,
|
||||||
const char *table_name_par, const char *field_name_par):
|
Item_in_subselect* master, Item **item,
|
||||||
Item_ref(item, table_name_par, field_name_par), owner(master) {}
|
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();
|
double val_real();
|
||||||
longlong val_int();
|
longlong val_int();
|
||||||
String* val_str(String* s);
|
String* val_str(String* s);
|
||||||
@ -1429,10 +1552,11 @@ class Item_null_helper :public Item_ref_null_helper
|
|||||||
{
|
{
|
||||||
Item *store;
|
Item *store;
|
||||||
public:
|
public:
|
||||||
Item_null_helper(Item_in_subselect* master, Item *item,
|
Item_null_helper(Name_resolution_context *context_arg,
|
||||||
const char *table_name_par, const char *field_name_par)
|
Item_in_subselect* master, Item *item,
|
||||||
:Item_ref_null_helper(master, (store= 0, &store), table_name_par,
|
const char *table_name_arg, const char *field_name_arg)
|
||||||
field_name_par),
|
:Item_ref_null_helper(context_arg, master, (store= 0, &store),
|
||||||
|
table_name_arg, field_name_arg),
|
||||||
store(item)
|
store(item)
|
||||||
{ ref= &store; }
|
{ ref= &store; }
|
||||||
void print(String *str);
|
void print(String *str);
|
||||||
@ -1583,13 +1707,17 @@ class Item_default_value : public Item_field
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Item *arg;
|
Item *arg;
|
||||||
Item_default_value() :
|
Item_default_value(Name_resolution_context *context_arg)
|
||||||
Item_field((const char *)NULL, (const char *)NULL, (const char *)NULL), arg(NULL) {}
|
:Item_field(context_arg, (const char *)NULL, (const char *)NULL,
|
||||||
Item_default_value(Item *a) :
|
(const char *)NULL),
|
||||||
Item_field((const char *)NULL, (const char *)NULL, (const char *)NULL), arg(a) {}
|
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; }
|
enum Type type() const { return DEFAULT_VALUE_ITEM; }
|
||||||
bool eq(const Item *item, bool binary_cmp) const;
|
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);
|
void print(String *str);
|
||||||
int save_in_field(Field *field_arg, bool no_conversions);
|
int save_in_field(Field *field_arg, bool no_conversions);
|
||||||
table_map used_tables() const { return (table_map)0L; }
|
table_map used_tables() const { return (table_map)0L; }
|
||||||
@ -1618,10 +1746,12 @@ class Item_insert_value : public Item_field
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Item *arg;
|
Item *arg;
|
||||||
Item_insert_value(Item *a) :
|
Item_insert_value(Name_resolution_context *context_arg, Item *a)
|
||||||
Item_field((const char *)NULL, (const char *)NULL, (const char *)NULL), arg(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 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);
|
void print(String *str);
|
||||||
int save_in_field(Field *field_arg, bool no_conversions)
|
int save_in_field(Field *field_arg, bool no_conversions)
|
||||||
{
|
{
|
||||||
@ -1683,15 +1813,17 @@ public:
|
|||||||
/* Pointer to Table_trigger_list object for table of this trigger */
|
/* Pointer to Table_trigger_list object for table of this trigger */
|
||||||
Table_triggers_list *triggers;
|
Table_triggers_list *triggers;
|
||||||
|
|
||||||
Item_trigger_field(row_version_type row_ver_par,
|
Item_trigger_field(Name_resolution_context *context_arg,
|
||||||
const char *field_name_par):
|
row_version_type row_ver_arg,
|
||||||
Item_field((const char *)NULL, (const char *)NULL, field_name_par),
|
const char *field_name_arg)
|
||||||
row_version(row_ver_par), field_idx((uint)-1)
|
: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);
|
void setup_field(THD *thd, TABLE *table);
|
||||||
enum Type type() const { return TRIGGER_FIELD_ITEM; }
|
enum Type type() const { return TRIGGER_FIELD_ITEM; }
|
||||||
bool eq(const Item *item, bool binary_cmp) const;
|
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);
|
void print(String *str);
|
||||||
table_map used_tables() const { return (table_map)0L; }
|
table_map used_tables() const { return (table_map)0L; }
|
||||||
void cleanup();
|
void cleanup();
|
||||||
@ -1880,7 +2012,7 @@ public:
|
|||||||
Item_type_holder(THD*, Item*);
|
Item_type_holder(THD*, Item*);
|
||||||
|
|
||||||
Item_result result_type() const;
|
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; }
|
enum Type type() const { return TYPE_HOLDER; }
|
||||||
double val_real();
|
double val_real();
|
||||||
longlong val_int();
|
longlong val_int();
|
||||||
@ -1892,6 +2024,7 @@ public:
|
|||||||
static enum_field_types get_real_type(Item *);
|
static enum_field_types get_real_type(Item *);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class st_select_lex;
|
class st_select_lex;
|
||||||
void mark_select_range_as_dependent(THD *thd,
|
void mark_select_range_as_dependent(THD *thd,
|
||||||
st_select_lex *last_select,
|
st_select_lex *last_select,
|
||||||
|
@ -638,11 +638,9 @@ int Arg_comparator::compare_e_row()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Item_in_optimizer::fix_left(THD *thd,
|
bool Item_in_optimizer::fix_left(THD *thd, Item **ref)
|
||||||
struct st_table_list *tables,
|
|
||||||
Item **ref)
|
|
||||||
{
|
{
|
||||||
if (!args[0]->fixed && args[0]->fix_fields(thd, tables, args) ||
|
if (!args[0]->fixed && args[0]->fix_fields(thd, args) ||
|
||||||
!cache && !(cache= Item_cache::get_cache(args[0]->result_type())))
|
!cache && !(cache= Item_cache::get_cache(args[0]->result_type())))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
@ -679,16 +677,15 @@ bool Item_in_optimizer::fix_left(THD *thd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Item_in_optimizer::fix_fields(THD *thd, struct st_table_list *tables,
|
bool Item_in_optimizer::fix_fields(THD *thd, Item **ref)
|
||||||
Item ** ref)
|
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 0);
|
DBUG_ASSERT(fixed == 0);
|
||||||
if (fix_left(thd, tables, ref))
|
if (fix_left(thd, ref))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
if (args[0]->maybe_null)
|
if (args[0]->maybe_null)
|
||||||
maybe_null=1;
|
maybe_null=1;
|
||||||
|
|
||||||
if (!args[1]->fixed && args[1]->fix_fields(thd, tables, args+1))
|
if (!args[1]->fixed && args[1]->fix_fields(thd, args+1))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
Item_in_subselect * sub= (Item_in_subselect *)args[1];
|
Item_in_subselect * sub= (Item_in_subselect *)args[1];
|
||||||
if (args[0]->cols() != sub->engine->cols())
|
if (args[0]->cols() != sub->engine->cols())
|
||||||
@ -2312,7 +2309,7 @@ void Item_cond::copy_andor_arguments(THD *thd, Item_cond *item)
|
|||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
Item_cond::fix_fields(THD *thd, Item **ref)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 0);
|
DBUG_ASSERT(fixed == 0);
|
||||||
List_iterator<Item> li(list);
|
List_iterator<Item> li(list);
|
||||||
@ -2360,7 +2357,7 @@ Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
|||||||
|
|
||||||
// item can be substituted in fix_fields
|
// item can be substituted in fix_fields
|
||||||
if ((!item->fixed &&
|
if ((!item->fixed &&
|
||||||
item->fix_fields(thd, tables, li.ref())) ||
|
item->fix_fields(thd, li.ref())) ||
|
||||||
(item= *li.ref())->check_cols(1))
|
(item= *li.ref())->check_cols(1))
|
||||||
return TRUE; /* purecov: inspected */
|
return TRUE; /* purecov: inspected */
|
||||||
used_tables_cache|= item->used_tables();
|
used_tables_cache|= item->used_tables();
|
||||||
@ -2747,11 +2744,11 @@ Item_func::optimize_type Item_func_like::select_optimize() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref)
|
bool Item_func_like::fix_fields(THD *thd, Item **ref)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 0);
|
DBUG_ASSERT(fixed == 0);
|
||||||
if (Item_bool_func2::fix_fields(thd, tlist, ref) ||
|
if (Item_bool_func2::fix_fields(thd, ref) ||
|
||||||
escape_item->fix_fields(thd, tlist, &escape_item))
|
escape_item->fix_fields(thd, &escape_item))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
if (!escape_item->const_during_execution())
|
if (!escape_item->const_during_execution())
|
||||||
@ -2815,13 +2812,13 @@ bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref)
|
|||||||
#ifdef USE_REGEX
|
#ifdef USE_REGEX
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
Item_func_regex::fix_fields(THD *thd, Item **ref)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 0);
|
DBUG_ASSERT(fixed == 0);
|
||||||
if ((!args[0]->fixed &&
|
if ((!args[0]->fixed &&
|
||||||
args[0]->fix_fields(thd, tables, args)) || args[0]->check_cols(1) ||
|
args[0]->fix_fields(thd, args)) || args[0]->check_cols(1) ||
|
||||||
(!args[1]->fixed &&
|
(!args[1]->fixed &&
|
||||||
args[1]->fix_fields(thd,tables, args + 1)) || args[1]->check_cols(1))
|
args[1]->fix_fields(thd, args + 1)) || args[1]->check_cols(1))
|
||||||
return TRUE; /* purecov: inspected */
|
return TRUE; /* purecov: inspected */
|
||||||
with_sum_func=args[0]->with_sum_func || args[1]->with_sum_func;
|
with_sum_func=args[0]->with_sum_func || args[1]->with_sum_func;
|
||||||
max_length= 1;
|
max_length= 1;
|
||||||
@ -3481,7 +3478,7 @@ void Item_equal::sort(Item_field_cmpfunc cmp, void *arg)
|
|||||||
} while (swap);
|
} while (swap);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Item_equal::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
bool Item_equal::fix_fields(THD *thd, Item **ref)
|
||||||
{
|
{
|
||||||
List_iterator_fast<Item_field> li(fields);
|
List_iterator_fast<Item_field> li(fields);
|
||||||
Item *item;
|
Item *item;
|
||||||
|
@ -108,8 +108,8 @@ public:
|
|||||||
Item_in_optimizer(Item *a, Item_in_subselect *b):
|
Item_in_optimizer(Item *a, Item_in_subselect *b):
|
||||||
Item_bool_func(a, my_reinterpret_cast(Item *)(b)), cache(0), save_cache(0)
|
Item_bool_func(a, my_reinterpret_cast(Item *)(b)), cache(0), save_cache(0)
|
||||||
{}
|
{}
|
||||||
bool fix_fields(THD *, struct st_table_list *, Item **);
|
bool fix_fields(THD *, Item **);
|
||||||
bool fix_left(THD *thd, struct st_table_list *tables, Item **ref);
|
bool fix_left(THD *thd, Item **ref);
|
||||||
bool is_null();
|
bool is_null();
|
||||||
/*
|
/*
|
||||||
Item_in_optimizer item is special boolean function. On value request
|
Item_in_optimizer item is special boolean function. On value request
|
||||||
@ -502,11 +502,11 @@ public:
|
|||||||
String *val_str(String *str);
|
String *val_str(String *str);
|
||||||
my_decimal *val_decimal(my_decimal *);
|
my_decimal *val_decimal(my_decimal *);
|
||||||
enum Item_result result_type () const { return cached_result_type; }
|
enum Item_result result_type () const { return cached_result_type; }
|
||||||
bool fix_fields(THD *thd,struct st_table_list *tlist, Item **ref)
|
bool fix_fields(THD *thd, Item **ref)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 0);
|
DBUG_ASSERT(fixed == 0);
|
||||||
args[0]->top_level_item();
|
args[0]->top_level_item();
|
||||||
return Item_func::fix_fields(thd, tlist, ref);
|
return Item_func::fix_fields(thd, ref);
|
||||||
}
|
}
|
||||||
void fix_length_and_dec();
|
void fix_length_and_dec();
|
||||||
uint decimal_precision() const;
|
uint decimal_precision() const;
|
||||||
@ -961,7 +961,7 @@ public:
|
|||||||
optimize_type select_optimize() const;
|
optimize_type select_optimize() const;
|
||||||
cond_result eq_cmp_result() const { return COND_TRUE; }
|
cond_result eq_cmp_result() const { return COND_TRUE; }
|
||||||
const char *func_name() const { return "like"; }
|
const char *func_name() const { return "like"; }
|
||||||
bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
|
bool fix_fields(THD *thd, Item **ref);
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef USE_REGEX
|
#ifdef USE_REGEX
|
||||||
@ -980,7 +980,7 @@ public:
|
|||||||
regex_compiled(0),regex_is_const(0) {}
|
regex_compiled(0),regex_is_const(0) {}
|
||||||
void cleanup();
|
void cleanup();
|
||||||
longlong val_int();
|
longlong val_int();
|
||||||
bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
|
bool fix_fields(THD *thd, Item **ref);
|
||||||
const char *func_name() const { return "regexp"; }
|
const char *func_name() const { return "regexp"; }
|
||||||
void print(String *str) { print_op(str); }
|
void print(String *str) { print_op(str); }
|
||||||
CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
|
CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
|
||||||
@ -1024,7 +1024,7 @@ public:
|
|||||||
:Item_bool_func(), list(nlist), abort_on_null(0) {}
|
:Item_bool_func(), list(nlist), abort_on_null(0) {}
|
||||||
bool add(Item *item) { return list.push_back(item); }
|
bool add(Item *item) { return list.push_back(item); }
|
||||||
void add_at_head(List<Item> *nlist) { list.prepand(nlist); }
|
void add_at_head(List<Item> *nlist) { list.prepand(nlist); }
|
||||||
bool fix_fields(THD *, struct st_table_list *, Item **ref);
|
bool fix_fields(THD *, Item **ref);
|
||||||
|
|
||||||
enum Type type() const { return COND_ITEM; }
|
enum Type type() const { return COND_ITEM; }
|
||||||
List<Item>* argument_list() { return &list; }
|
List<Item>* argument_list() { return &list; }
|
||||||
@ -1141,7 +1141,7 @@ public:
|
|||||||
void sort(Item_field_cmpfunc cmp, void *arg);
|
void sort(Item_field_cmpfunc cmp, void *arg);
|
||||||
friend class Item_equal_iterator;
|
friend class Item_equal_iterator;
|
||||||
void fix_length_and_dec();
|
void fix_length_and_dec();
|
||||||
bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref);
|
bool fix_fields(THD *thd, Item **ref);
|
||||||
void update_used_tables();
|
void update_used_tables();
|
||||||
bool walk(Item_processor processor, byte *arg);
|
bool walk(Item_processor processor, byte *arg);
|
||||||
Item *transform(Item_transformer transformer, byte *arg);
|
Item *transform(Item_transformer transformer, byte *arg);
|
||||||
|
@ -194,11 +194,10 @@ bool Item_func::agg_arg_charsets(DTCollation &coll,
|
|||||||
((Item_field *)(*arg))->no_const_subst= 1;
|
((Item_field *)(*arg))->no_const_subst= 1;
|
||||||
/*
|
/*
|
||||||
We do not check conv->fixed, because Item_func_conv_charset which can
|
We do not check conv->fixed, because Item_func_conv_charset which can
|
||||||
be return by safe_charset_converter can't be fixed at creation, also
|
be return by safe_charset_converter can't be fixed at creation
|
||||||
it do not need tables (second argument) for name resolving
|
|
||||||
*/
|
*/
|
||||||
*arg= conv;
|
*arg= conv;
|
||||||
conv->fix_fields(thd, 0, arg);
|
conv->fix_fields(thd, arg);
|
||||||
}
|
}
|
||||||
if (arena)
|
if (arena)
|
||||||
thd->restore_backup_item_arena(arena, &backup);
|
thd->restore_backup_item_arena(arena, &backup);
|
||||||
@ -261,7 +260,6 @@ Item_func::Item_func(THD *thd, Item_func *item)
|
|||||||
SYNOPSIS:
|
SYNOPSIS:
|
||||||
fix_fields()
|
fix_fields()
|
||||||
thd Thread object
|
thd Thread object
|
||||||
tables List of all open tables involved in the query
|
|
||||||
ref Pointer to where this object is used. This reference
|
ref Pointer to where this object is used. This reference
|
||||||
is used if we want to replace this object with another
|
is used if we want to replace this object with another
|
||||||
one (for example in the summary functions).
|
one (for example in the summary functions).
|
||||||
@ -290,7 +288,7 @@ Item_func::Item_func(THD *thd, Item_func *item)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
Item_func::fix_fields(THD *thd, Item **ref)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 0);
|
DBUG_ASSERT(fixed == 0);
|
||||||
Item **arg,**arg_end;
|
Item **arg,**arg_end;
|
||||||
@ -312,7 +310,7 @@ Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
|||||||
We can't yet set item to *arg as fix_fields may change *arg
|
We can't yet set item to *arg as fix_fields may change *arg
|
||||||
We shouldn't call fix_fields() twice, so check 'fixed' field first
|
We shouldn't call fix_fields() twice, so check 'fixed' field first
|
||||||
*/
|
*/
|
||||||
if ((!(*arg)->fixed && (*arg)->fix_fields(thd, tables, arg)))
|
if ((!(*arg)->fixed && (*arg)->fix_fields(thd, arg)))
|
||||||
return TRUE; /* purecov: inspected */
|
return TRUE; /* purecov: inspected */
|
||||||
item= *arg;
|
item= *arg;
|
||||||
|
|
||||||
@ -2010,10 +2008,9 @@ my_decimal *Item_func_round::decimal_op(my_decimal *decimal_value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Item_func_rand::fix_fields(THD *thd, struct st_table_list *tables,
|
bool Item_func_rand::fix_fields(THD *thd,Item **ref)
|
||||||
Item **ref)
|
|
||||||
{
|
{
|
||||||
if (Item_real_func::fix_fields(thd, tables, ref))
|
if (Item_real_func::fix_fields(thd, ref))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
used_tables_cache|= RAND_TABLE_BIT;
|
used_tables_cache|= RAND_TABLE_BIT;
|
||||||
if (arg_count)
|
if (arg_count)
|
||||||
@ -2604,7 +2601,7 @@ void udf_handler::cleanup()
|
|||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func,
|
udf_handler::fix_fields(THD *thd, Item_result_field *func,
|
||||||
uint arg_count, Item **arguments)
|
uint arg_count, Item **arguments)
|
||||||
{
|
{
|
||||||
#ifndef EMBEDDED_LIBRARY // Avoid compiler warning
|
#ifndef EMBEDDED_LIBRARY // Avoid compiler warning
|
||||||
@ -2646,7 +2643,7 @@ udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func,
|
|||||||
arg++,i++)
|
arg++,i++)
|
||||||
{
|
{
|
||||||
if (!(*arg)->fixed &&
|
if (!(*arg)->fixed &&
|
||||||
(*arg)->fix_fields(thd, tables, arg))
|
(*arg)->fix_fields(thd, arg))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
// we can't assign 'item' before, because fix_fields() can change arg
|
// we can't assign 'item' before, because fix_fields() can change arg
|
||||||
Item *item= *arg;
|
Item *item= *arg;
|
||||||
@ -3458,12 +3455,11 @@ static user_var_entry *get_variable(HASH *hash, LEX_STRING &name,
|
|||||||
SELECT @a:= ).
|
SELECT @a:= ).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool Item_func_set_user_var::fix_fields(THD *thd, TABLE_LIST *tables,
|
bool Item_func_set_user_var::fix_fields(THD *thd, Item **ref)
|
||||||
Item **ref)
|
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 0);
|
DBUG_ASSERT(fixed == 0);
|
||||||
/* fix_fields will call Item_func_set_user_var::fix_length_and_dec */
|
/* fix_fields will call Item_func_set_user_var::fix_length_and_dec */
|
||||||
if (Item_func::fix_fields(thd, tables, ref) ||
|
if (Item_func::fix_fields(thd, ref) ||
|
||||||
!(entry= get_variable(&thd->user_vars, name, 1)))
|
!(entry= get_variable(&thd->user_vars, name, 1)))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
/*
|
/*
|
||||||
@ -4127,11 +4123,10 @@ bool Item_func_get_user_var::eq(const Item *item, bool binary_cmp) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Item_user_var_as_out_param::fix_fields(THD *thd, TABLE_LIST *tables,
|
bool Item_user_var_as_out_param::fix_fields(THD *thd, Item **ref)
|
||||||
Item **ref)
|
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 0);
|
DBUG_ASSERT(fixed == 0);
|
||||||
if (Item::fix_fields(thd, tables, ref) ||
|
if (Item::fix_fields(thd, ref) ||
|
||||||
!(entry= get_variable(&thd->user_vars, name, 1)))
|
!(entry= get_variable(&thd->user_vars, name, 1)))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
entry->type= STRING_RESULT;
|
entry->type= STRING_RESULT;
|
||||||
@ -4314,7 +4309,7 @@ void Item_func_match::init_search(bool no_order)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Item_func_match::fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
|
bool Item_func_match::fix_fields(THD *thd, Item **ref)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 0);
|
DBUG_ASSERT(fixed == 0);
|
||||||
Item *item;
|
Item *item;
|
||||||
@ -4329,7 +4324,7 @@ bool Item_func_match::fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
|
|||||||
modifications to find_best and auto_close as complement to auto_init code
|
modifications to find_best and auto_close as complement to auto_init code
|
||||||
above.
|
above.
|
||||||
*/
|
*/
|
||||||
if (Item_func::fix_fields(thd, tlist, ref) ||
|
if (Item_func::fix_fields(thd, ref) ||
|
||||||
!args[0]->const_during_execution())
|
!args[0]->const_during_execution())
|
||||||
{
|
{
|
||||||
my_error(ER_WRONG_ARGUMENTS,MYF(0),"AGAINST");
|
my_error(ER_WRONG_ARGUMENTS,MYF(0),"AGAINST");
|
||||||
@ -4690,8 +4685,9 @@ longlong Item_func_row_count::val_int()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Item_func_sp::Item_func_sp(sp_name *name)
|
Item_func_sp::Item_func_sp(Name_resolution_context *context_arg, sp_name *name)
|
||||||
:Item_func(), m_name(name), m_sp(NULL), result_field(NULL)
|
:Item_func(), context(context_arg), m_name(name), m_sp(NULL),
|
||||||
|
result_field(NULL)
|
||||||
{
|
{
|
||||||
maybe_null= 1;
|
maybe_null= 1;
|
||||||
m_name->init_qname(current_thd);
|
m_name->init_qname(current_thd);
|
||||||
@ -4699,8 +4695,10 @@ Item_func_sp::Item_func_sp(sp_name *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Item_func_sp::Item_func_sp(sp_name *name, List<Item> &list)
|
Item_func_sp::Item_func_sp(Name_resolution_context *context_arg,
|
||||||
:Item_func(list), m_name(name), m_sp(NULL), result_field(NULL)
|
sp_name *name, List<Item> &list)
|
||||||
|
:Item_func(list), context(context_arg), m_name(name), m_sp(NULL),
|
||||||
|
result_field(NULL)
|
||||||
{
|
{
|
||||||
maybe_null= 1;
|
maybe_null= 1;
|
||||||
m_name->init_qname(current_thd);
|
m_name->init_qname(current_thd);
|
||||||
@ -4944,7 +4942,10 @@ Item_func_sp::fix_length_and_dec()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!(field= sp_result_field()))
|
if (!(field= sp_result_field()))
|
||||||
|
{
|
||||||
|
context->process_error(current_thd);
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
|
}
|
||||||
decimals= field->decimals();
|
decimals= field->decimals();
|
||||||
max_length= field->field_length;
|
max_length= field->field_length;
|
||||||
maybe_null= 1;
|
maybe_null= 1;
|
||||||
|
@ -116,7 +116,7 @@ public:
|
|||||||
Item_func(List<Item> &list);
|
Item_func(List<Item> &list);
|
||||||
// Constructor used for Item_cond_and/or (see Item comment)
|
// Constructor used for Item_cond_and/or (see Item comment)
|
||||||
Item_func(THD *thd, Item_func *item);
|
Item_func(THD *thd, Item_func *item);
|
||||||
bool fix_fields(THD *,struct st_table_list *, Item **ref);
|
bool fix_fields(THD *, Item **ref);
|
||||||
table_map used_tables() const;
|
table_map used_tables() const;
|
||||||
table_map not_null_tables() const;
|
table_map not_null_tables() const;
|
||||||
void update_used_tables();
|
void update_used_tables();
|
||||||
@ -630,7 +630,7 @@ public:
|
|||||||
const char *func_name() const { return "rand"; }
|
const char *func_name() const { return "rand"; }
|
||||||
bool const_item() const { return 0; }
|
bool const_item() const { return 0; }
|
||||||
void update_used_tables();
|
void update_used_tables();
|
||||||
bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref);
|
bool fix_fields(THD *thd, Item **ref);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -885,14 +885,15 @@ protected:
|
|||||||
udf_handler udf;
|
udf_handler udf;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Item_udf_func(udf_func *udf_arg) :Item_func(), udf(udf_arg) {}
|
Item_udf_func(udf_func *udf_arg)
|
||||||
|
:Item_func(), udf(udf_arg) {}
|
||||||
Item_udf_func(udf_func *udf_arg, List<Item> &list)
|
Item_udf_func(udf_func *udf_arg, List<Item> &list)
|
||||||
:Item_func(list), udf(udf_arg) {}
|
:Item_func(list), udf(udf_arg) {}
|
||||||
const char *func_name() const { return udf.name(); }
|
const char *func_name() const { return udf.name(); }
|
||||||
bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref)
|
bool fix_fields(THD *thd, Item **ref)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 0);
|
DBUG_ASSERT(fixed == 0);
|
||||||
bool res= udf.fix_fields(thd, tables, this, arg_count, args);
|
bool res= udf.fix_fields(thd, this, arg_count, args);
|
||||||
used_tables_cache= udf.used_tables_cache;
|
used_tables_cache= udf.used_tables_cache;
|
||||||
const_item_cache= udf.const_item_cache;
|
const_item_cache= udf.const_item_cache;
|
||||||
fixed= 1;
|
fixed= 1;
|
||||||
@ -907,8 +908,10 @@ public:
|
|||||||
class Item_func_udf_float :public Item_udf_func
|
class Item_func_udf_float :public Item_udf_func
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Item_func_udf_float(udf_func *udf_arg) :Item_udf_func(udf_arg) {}
|
Item_func_udf_float(udf_func *udf_arg)
|
||||||
Item_func_udf_float(udf_func *udf_arg, List<Item> &list)
|
:Item_udf_func(udf_arg) {}
|
||||||
|
Item_func_udf_float(udf_func *udf_arg,
|
||||||
|
List<Item> &list)
|
||||||
:Item_udf_func(udf_arg, list) {}
|
:Item_udf_func(udf_arg, list) {}
|
||||||
longlong val_int()
|
longlong val_int()
|
||||||
{
|
{
|
||||||
@ -932,8 +935,10 @@ class Item_func_udf_float :public Item_udf_func
|
|||||||
class Item_func_udf_int :public Item_udf_func
|
class Item_func_udf_int :public Item_udf_func
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Item_func_udf_int(udf_func *udf_arg) :Item_udf_func(udf_arg) {}
|
Item_func_udf_int(udf_func *udf_arg)
|
||||||
Item_func_udf_int(udf_func *udf_arg, List<Item> &list)
|
:Item_udf_func(udf_arg) {}
|
||||||
|
Item_func_udf_int(udf_func *udf_arg,
|
||||||
|
List<Item> &list)
|
||||||
:Item_udf_func(udf_arg, list) {}
|
:Item_udf_func(udf_arg, list) {}
|
||||||
longlong val_int();
|
longlong val_int();
|
||||||
double val_real() { return (double) Item_func_udf_int::val_int(); }
|
double val_real() { return (double) Item_func_udf_int::val_int(); }
|
||||||
@ -946,7 +951,8 @@ public:
|
|||||||
class Item_func_udf_decimal :public Item_udf_func
|
class Item_func_udf_decimal :public Item_udf_func
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Item_func_udf_decimal(udf_func *udf_arg) :Item_udf_func(udf_arg) {}
|
Item_func_udf_decimal(udf_func *udf_arg)
|
||||||
|
:Item_udf_func(udf_arg) {}
|
||||||
Item_func_udf_decimal(udf_func *udf_arg, List<Item> &list)
|
Item_func_udf_decimal(udf_func *udf_arg, List<Item> &list)
|
||||||
:Item_udf_func(udf_arg, list) {}
|
:Item_udf_func(udf_arg, list) {}
|
||||||
longlong val_int();
|
longlong val_int();
|
||||||
@ -961,7 +967,8 @@ public:
|
|||||||
class Item_func_udf_str :public Item_udf_func
|
class Item_func_udf_str :public Item_udf_func
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Item_func_udf_str(udf_func *udf_arg) :Item_udf_func(udf_arg) {}
|
Item_func_udf_str(udf_func *udf_arg)
|
||||||
|
:Item_udf_func(udf_arg) {}
|
||||||
Item_func_udf_str(udf_func *udf_arg, List<Item> &list)
|
Item_func_udf_str(udf_func *udf_arg, List<Item> &list)
|
||||||
:Item_udf_func(udf_arg, list) {}
|
:Item_udf_func(udf_arg, list) {}
|
||||||
String *val_str(String *);
|
String *val_str(String *);
|
||||||
@ -998,8 +1005,10 @@ public:
|
|||||||
class Item_func_udf_float :public Item_real_func
|
class Item_func_udf_float :public Item_real_func
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Item_func_udf_float(udf_func *udf_arg) :Item_real_func() {}
|
Item_func_udf_float(udf_func *udf_arg)
|
||||||
Item_func_udf_float(udf_func *udf_arg, List<Item> &list) :Item_real_func(list) {}
|
:Item_real_func() {}
|
||||||
|
Item_func_udf_float(udf_func *udf_arg, List<Item> &list)
|
||||||
|
:Item_real_func(list) {}
|
||||||
double val_real() { DBUG_ASSERT(fixed == 1); return 0.0; }
|
double val_real() { DBUG_ASSERT(fixed == 1); return 0.0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1007,8 +1016,10 @@ class Item_func_udf_float :public Item_real_func
|
|||||||
class Item_func_udf_int :public Item_int_func
|
class Item_func_udf_int :public Item_int_func
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Item_func_udf_int(udf_func *udf_arg) :Item_int_func() {}
|
Item_func_udf_int(udf_func *udf_arg)
|
||||||
Item_func_udf_int(udf_func *udf_arg, List<Item> &list) :Item_int_func(list) {}
|
:Item_int_func() {}
|
||||||
|
Item_func_udf_int(udf_func *udf_arg, List<Item> &list)
|
||||||
|
:Item_int_func(list) {}
|
||||||
longlong val_int() { DBUG_ASSERT(fixed == 1); return 0; }
|
longlong val_int() { DBUG_ASSERT(fixed == 1); return 0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1016,8 +1027,10 @@ public:
|
|||||||
class Item_func_udf_decimal :public Item_int_func
|
class Item_func_udf_decimal :public Item_int_func
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Item_func_udf_decimal(udf_func *udf_arg) :Item_int_func() {}
|
Item_func_udf_decimal(udf_func *udf_arg)
|
||||||
Item_func_udf_decimal(udf_func *udf_arg, List<Item> &list) :Item_int_func(list) {}
|
:Item_int_func() {}
|
||||||
|
Item_func_udf_decimal(udf_func *udf_arg, List<Item> &list)
|
||||||
|
:Item_int_func(list) {}
|
||||||
my_decimal *val_decimal(my_decimal *) { DBUG_ASSERT(fixed == 1); return 0; }
|
my_decimal *val_decimal(my_decimal *) { DBUG_ASSERT(fixed == 1); return 0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1025,8 +1038,10 @@ public:
|
|||||||
class Item_func_udf_str :public Item_func
|
class Item_func_udf_str :public Item_func
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Item_func_udf_str(udf_func *udf_arg) :Item_func() {}
|
Item_func_udf_str(udf_func *udf_arg)
|
||||||
Item_func_udf_str(udf_func *udf_arg, List<Item> &list) :Item_func(list) {}
|
:Item_func() {}
|
||||||
|
Item_func_udf_str(udf_func *udf_arg, List<Item> &list)
|
||||||
|
:Item_func(list) {}
|
||||||
String *val_str(String *)
|
String *val_str(String *)
|
||||||
{ DBUG_ASSERT(fixed == 1); null_value=1; return 0; }
|
{ DBUG_ASSERT(fixed == 1); null_value=1; return 0; }
|
||||||
double val_real() { DBUG_ASSERT(fixed == 1); null_value= 1; return 0.0; }
|
double val_real() { DBUG_ASSERT(fixed == 1); null_value= 1; return 0.0; }
|
||||||
@ -1116,7 +1131,7 @@ public:
|
|||||||
bool check();
|
bool check();
|
||||||
bool update();
|
bool update();
|
||||||
enum Item_result result_type () const { return cached_result_type; }
|
enum Item_result result_type () const { return cached_result_type; }
|
||||||
bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref);
|
bool fix_fields(THD *thd, Item **ref);
|
||||||
void fix_length_and_dec();
|
void fix_length_and_dec();
|
||||||
void print(String *str);
|
void print(String *str);
|
||||||
void print_as_stmt(String *str);
|
void print_as_stmt(String *str);
|
||||||
@ -1176,7 +1191,7 @@ public:
|
|||||||
String *val_str(String *str);
|
String *val_str(String *str);
|
||||||
my_decimal *val_decimal(my_decimal *decimal_buffer);
|
my_decimal *val_decimal(my_decimal *decimal_buffer);
|
||||||
/* fix_fields() binds variable name with its entry structure */
|
/* fix_fields() binds variable name with its entry structure */
|
||||||
bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref);
|
bool fix_fields(THD *thd, Item **ref);
|
||||||
void print(String *str);
|
void print(String *str);
|
||||||
void set_null_value(CHARSET_INFO* cs);
|
void set_null_value(CHARSET_INFO* cs);
|
||||||
void set_value(const char *str, uint length, CHARSET_INFO* cs);
|
void set_value(const char *str, uint length, CHARSET_INFO* cs);
|
||||||
@ -1230,7 +1245,7 @@ public:
|
|||||||
const char *func_name() const { return "match"; }
|
const char *func_name() const { return "match"; }
|
||||||
void update_used_tables() {}
|
void update_used_tables() {}
|
||||||
table_map not_null_tables() const { return 0; }
|
table_map not_null_tables() const { return 0; }
|
||||||
bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
|
bool fix_fields(THD *thd, Item **ref);
|
||||||
bool eq(const Item *, bool binary_cmp) const;
|
bool eq(const Item *, bool binary_cmp) const;
|
||||||
/* The following should be safe, even if we compare doubles */
|
/* The following should be safe, even if we compare doubles */
|
||||||
longlong val_int() { DBUG_ASSERT(fixed == 1); return val_real() != 0.0; }
|
longlong val_int() { DBUG_ASSERT(fixed == 1); return val_real() != 0.0; }
|
||||||
@ -1302,6 +1317,7 @@ class sp_name;
|
|||||||
class Item_func_sp :public Item_func
|
class Item_func_sp :public Item_func
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
Name_resolution_context *context;
|
||||||
sp_name *m_name;
|
sp_name *m_name;
|
||||||
mutable sp_head *m_sp;
|
mutable sp_head *m_sp;
|
||||||
TABLE *dummy_table;
|
TABLE *dummy_table;
|
||||||
@ -1314,9 +1330,10 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Item_func_sp(sp_name *name);
|
Item_func_sp(Name_resolution_context *context_arg, sp_name *name);
|
||||||
|
|
||||||
Item_func_sp(sp_name *name, List<Item> &list);
|
Item_func_sp(Name_resolution_context *context_arg,
|
||||||
|
sp_name *name, List<Item> &list);
|
||||||
|
|
||||||
virtual ~Item_func_sp()
|
virtual ~Item_func_sp()
|
||||||
{}
|
{}
|
||||||
@ -1361,6 +1378,9 @@ public:
|
|||||||
return result_field->val_str(str);
|
return result_field->val_str(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual bool change_context_processor(byte *cntx)
|
||||||
|
{ context= (Name_resolution_context *)cntx; return FALSE; }
|
||||||
|
|
||||||
void fix_length_and_dec();
|
void fix_length_and_dec();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -53,7 +53,7 @@ void Item_row::illegal_method_call(const char *method)
|
|||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Item_row::fix_fields(THD *thd, TABLE_LIST *tabl, Item **ref)
|
bool Item_row::fix_fields(THD *thd, Item **ref)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 0);
|
DBUG_ASSERT(fixed == 0);
|
||||||
null_value= 0;
|
null_value= 0;
|
||||||
@ -61,7 +61,7 @@ bool Item_row::fix_fields(THD *thd, TABLE_LIST *tabl, Item **ref)
|
|||||||
Item **arg, **arg_end;
|
Item **arg, **arg_end;
|
||||||
for (arg= items, arg_end= items+arg_count; arg != arg_end ; arg++)
|
for (arg= items, arg_end= items+arg_count; arg != arg_end ; arg++)
|
||||||
{
|
{
|
||||||
if ((*arg)->fix_fields(thd, tabl, arg))
|
if ((*arg)->fix_fields(thd, arg))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
// we can't assign 'item' before, because fix_fields() can change arg
|
// we can't assign 'item' before, because fix_fields() can change arg
|
||||||
Item *item= *arg;
|
Item *item= *arg;
|
||||||
|
@ -61,7 +61,7 @@ public:
|
|||||||
illegal_method_call((const char*)"val_decimal");
|
illegal_method_call((const char*)"val_decimal");
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref);
|
bool fix_fields(THD *thd, Item **ref);
|
||||||
void split_sum_func(THD *thd, Item **ref_pointer_array, List<Item> &fields);
|
void split_sum_func(THD *thd, Item **ref_pointer_array, List<Item> &fields);
|
||||||
table_map used_tables() const { return used_tables_cache; };
|
table_map used_tables() const { return used_tables_cache; };
|
||||||
bool const_item() const { return const_item_cache; };
|
bool const_item() const { return const_item_cache; };
|
||||||
|
@ -461,7 +461,7 @@ String *Item_func_des_decrypt::val_str(String *str)
|
|||||||
struct st_des_keyblock keyblock;
|
struct st_des_keyblock keyblock;
|
||||||
struct st_des_keyschedule keyschedule;
|
struct st_des_keyschedule keyschedule;
|
||||||
String *res= args[0]->val_str(str);
|
String *res= args[0]->val_str(str);
|
||||||
uint length=res->length(),tail;
|
uint length= 0, tail;
|
||||||
|
|
||||||
if ((null_value=args[0]->null_value))
|
if ((null_value=args[0]->null_value))
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -415,12 +415,12 @@ class Item_func_make_set :public Item_str_func
|
|||||||
public:
|
public:
|
||||||
Item_func_make_set(Item *a,List<Item> &list) :Item_str_func(list),item(a) {}
|
Item_func_make_set(Item *a,List<Item> &list) :Item_str_func(list),item(a) {}
|
||||||
String *val_str(String *str);
|
String *val_str(String *str);
|
||||||
bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
|
bool fix_fields(THD *thd, Item **ref)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 0);
|
DBUG_ASSERT(fixed == 0);
|
||||||
return ((!item->fixed && item->fix_fields(thd, tlist, &item)) ||
|
return ((!item->fixed && item->fix_fields(thd, &item)) ||
|
||||||
item->check_cols(1) ||
|
item->check_cols(1) ||
|
||||||
Item_func::fix_fields(thd, tlist, ref));
|
Item_func::fix_fields(thd, ref));
|
||||||
}
|
}
|
||||||
void split_sum_func(THD *thd, Item **ref_pointer_array, List<Item> &fields);
|
void split_sum_func(THD *thd, Item **ref_pointer_array, List<Item> &fields);
|
||||||
void fix_length_and_dec();
|
void fix_length_and_dec();
|
||||||
|
@ -130,7 +130,7 @@ Item_subselect::select_transformer(JOIN *join)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref)
|
bool Item_subselect::fix_fields(THD *thd_param, Item **ref)
|
||||||
{
|
{
|
||||||
char const *save_where= thd_param->where;
|
char const *save_where= thd_param->where;
|
||||||
bool res;
|
bool res;
|
||||||
@ -165,7 +165,7 @@ bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref)
|
|||||||
substitution= 0;
|
substitution= 0;
|
||||||
thd->where= "checking transformed subquery";
|
thd->where= "checking transformed subquery";
|
||||||
if (!(*ref)->fixed)
|
if (!(*ref)->fixed)
|
||||||
ret= (*ref)->fix_fields(thd, tables, ref);
|
ret= (*ref)->fix_fields(thd, ref);
|
||||||
thd->where= save_where;
|
thd->where= save_where;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -833,7 +833,7 @@ Item_in_subselect::single_value_transformer(JOIN *join,
|
|||||||
reference, also Item_sum_(max|min) can't be fixed after creation, so
|
reference, also Item_sum_(max|min) can't be fixed after creation, so
|
||||||
we do not check item->fixed
|
we do not check item->fixed
|
||||||
*/
|
*/
|
||||||
if (item->fix_fields(thd, join->tables_list, 0))
|
if (item->fix_fields(thd, 0))
|
||||||
DBUG_RETURN(RES_ERROR);
|
DBUG_RETURN(RES_ERROR);
|
||||||
/* we added aggregate function => we have to change statistic */
|
/* we added aggregate function => we have to change statistic */
|
||||||
count_field_types(&join->tmp_table_param, join->all_fields, 0);
|
count_field_types(&join->tmp_table_param, join->all_fields, 0);
|
||||||
@ -862,7 +862,7 @@ Item_in_subselect::single_value_transformer(JOIN *join,
|
|||||||
|
|
||||||
thd->lex->current_select= up= current->return_after_parsing();
|
thd->lex->current_select= up= current->return_after_parsing();
|
||||||
//optimizer never use Item **ref => we can pass 0 as parameter
|
//optimizer never use Item **ref => we can pass 0 as parameter
|
||||||
if (!optimizer || optimizer->fix_left(thd, up->get_table_list(), 0))
|
if (!optimizer || optimizer->fix_left(thd, 0))
|
||||||
{
|
{
|
||||||
thd->lex->current_select= current;
|
thd->lex->current_select= current;
|
||||||
DBUG_RETURN(RES_ERROR);
|
DBUG_RETURN(RES_ERROR);
|
||||||
@ -873,7 +873,8 @@ Item_in_subselect::single_value_transformer(JOIN *join,
|
|||||||
As far as Item_ref_in_optimizer do not substitute itself on fix_fields
|
As far as Item_ref_in_optimizer do not substitute itself on fix_fields
|
||||||
we can use same item for all selects.
|
we can use same item for all selects.
|
||||||
*/
|
*/
|
||||||
expr= new Item_direct_ref((Item**)optimizer->get_cache(),
|
expr= new Item_direct_ref(&select_lex->context,
|
||||||
|
(Item**)optimizer->get_cache(),
|
||||||
(char *)"<no matter>",
|
(char *)"<no matter>",
|
||||||
(char *)in_left_expr_name);
|
(char *)in_left_expr_name);
|
||||||
|
|
||||||
@ -893,7 +894,8 @@ Item_in_subselect::single_value_transformer(JOIN *join,
|
|||||||
{
|
{
|
||||||
bool tmp;
|
bool tmp;
|
||||||
Item *item= func->create(expr,
|
Item *item= func->create(expr,
|
||||||
new Item_ref_null_helper(this,
|
new Item_ref_null_helper(&select_lex->context,
|
||||||
|
this,
|
||||||
select_lex->
|
select_lex->
|
||||||
ref_pointer_array,
|
ref_pointer_array,
|
||||||
(char *)"<ref>",
|
(char *)"<ref>",
|
||||||
@ -913,7 +915,7 @@ Item_in_subselect::single_value_transformer(JOIN *join,
|
|||||||
we do not check join->having->fixed, because Item_and (from and_items)
|
we do not check join->having->fixed, because Item_and (from and_items)
|
||||||
or comparison function (from func->create) can't be fixed after creation
|
or comparison function (from func->create) can't be fixed after creation
|
||||||
*/
|
*/
|
||||||
tmp= join->having->fix_fields(thd, join->tables_list, 0);
|
tmp= join->having->fix_fields(thd, 0);
|
||||||
select_lex->having_fix_field= 0;
|
select_lex->having_fix_field= 0;
|
||||||
if (tmp)
|
if (tmp)
|
||||||
DBUG_RETURN(RES_ERROR);
|
DBUG_RETURN(RES_ERROR);
|
||||||
@ -949,7 +951,7 @@ Item_in_subselect::single_value_transformer(JOIN *join,
|
|||||||
and_items) or comparison function (from func->create) can't be
|
and_items) or comparison function (from func->create) can't be
|
||||||
fixed after creation
|
fixed after creation
|
||||||
*/
|
*/
|
||||||
tmp= join->having->fix_fields(thd, join->tables_list, 0);
|
tmp= join->having->fix_fields(thd, 0);
|
||||||
select_lex->having_fix_field= 0;
|
select_lex->having_fix_field= 0;
|
||||||
if (tmp)
|
if (tmp)
|
||||||
DBUG_RETURN(RES_ERROR);
|
DBUG_RETURN(RES_ERROR);
|
||||||
@ -971,7 +973,7 @@ Item_in_subselect::single_value_transformer(JOIN *join,
|
|||||||
we do not check join->conds->fixed, because Item_and can't be fixed
|
we do not check join->conds->fixed, because Item_and can't be fixed
|
||||||
after creation
|
after creation
|
||||||
*/
|
*/
|
||||||
if (join->conds->fix_fields(thd, join->tables_list, 0))
|
if (join->conds->fix_fields(thd, 0))
|
||||||
DBUG_RETURN(RES_ERROR);
|
DBUG_RETURN(RES_ERROR);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -985,7 +987,8 @@ Item_in_subselect::single_value_transformer(JOIN *join,
|
|||||||
argument (reference) to fix_fields()
|
argument (reference) to fix_fields()
|
||||||
*/
|
*/
|
||||||
item= func->create(expr,
|
item= func->create(expr,
|
||||||
new Item_null_helper(this, item,
|
new Item_null_helper(&select_lex->context,
|
||||||
|
this, item,
|
||||||
(char *)"<no matter>",
|
(char *)"<no matter>",
|
||||||
(char *)"<result>"));
|
(char *)"<result>"));
|
||||||
#ifdef CORRECT_BUT_TOO_SLOW_TO_BE_USABLE
|
#ifdef CORRECT_BUT_TOO_SLOW_TO_BE_USABLE
|
||||||
@ -998,7 +1001,7 @@ Item_in_subselect::single_value_transformer(JOIN *join,
|
|||||||
we do not check join->having->fixed, because comparison function
|
we do not check join->having->fixed, because comparison function
|
||||||
(from func->create) can't be fixed after creation
|
(from func->create) can't be fixed after creation
|
||||||
*/
|
*/
|
||||||
tmp= join->having->fix_fields(thd, join->tables_list, 0);
|
tmp= join->having->fix_fields(thd, 0);
|
||||||
select_lex->having_fix_field= 0;
|
select_lex->having_fix_field= 0;
|
||||||
if (tmp)
|
if (tmp)
|
||||||
DBUG_RETURN(RES_ERROR);
|
DBUG_RETURN(RES_ERROR);
|
||||||
@ -1048,7 +1051,7 @@ Item_in_subselect::row_value_transformer(JOIN *join)
|
|||||||
SELECT_LEX *current= thd->lex->current_select, *up;
|
SELECT_LEX *current= thd->lex->current_select, *up;
|
||||||
thd->lex->current_select= up= current->return_after_parsing();
|
thd->lex->current_select= up= current->return_after_parsing();
|
||||||
//optimizer never use Item **ref => we can pass 0 as parameter
|
//optimizer never use Item **ref => we can pass 0 as parameter
|
||||||
if (!optimizer || optimizer->fix_left(thd, up->get_table_list(), 0))
|
if (!optimizer || optimizer->fix_left(thd, 0))
|
||||||
{
|
{
|
||||||
thd->lex->current_select= current;
|
thd->lex->current_select= current;
|
||||||
DBUG_RETURN(RES_ERROR);
|
DBUG_RETURN(RES_ERROR);
|
||||||
@ -1071,12 +1074,14 @@ Item_in_subselect::row_value_transformer(JOIN *join)
|
|||||||
if (select_lex->ref_pointer_array[i]->
|
if (select_lex->ref_pointer_array[i]->
|
||||||
check_cols(left_expr->el(i)->cols()))
|
check_cols(left_expr->el(i)->cols()))
|
||||||
DBUG_RETURN(RES_ERROR);
|
DBUG_RETURN(RES_ERROR);
|
||||||
Item *func= new Item_ref_null_helper(this,
|
Item *func= new Item_ref_null_helper(&select_lex->context,
|
||||||
|
this,
|
||||||
select_lex->ref_pointer_array+i,
|
select_lex->ref_pointer_array+i,
|
||||||
(char *) "<no matter>",
|
(char *) "<no matter>",
|
||||||
(char *) "<list ref>");
|
(char *) "<list ref>");
|
||||||
func=
|
func=
|
||||||
eq_creator.create(new Item_direct_ref((*optimizer->get_cache())->
|
eq_creator.create(new Item_direct_ref(&select_lex->context,
|
||||||
|
(*optimizer->get_cache())->
|
||||||
addr(i),
|
addr(i),
|
||||||
(char *)"<no matter>",
|
(char *)"<no matter>",
|
||||||
(char *)in_left_expr_name),
|
(char *)in_left_expr_name),
|
||||||
@ -1099,7 +1104,7 @@ Item_in_subselect::row_value_transformer(JOIN *join)
|
|||||||
join->having can't be fixed after creation, so we do not check
|
join->having can't be fixed after creation, so we do not check
|
||||||
join->having->fixed
|
join->having->fixed
|
||||||
*/
|
*/
|
||||||
if (join->having->fix_fields(thd, join->tables_list, 0))
|
if (join->having->fix_fields(thd, 0))
|
||||||
{
|
{
|
||||||
select_lex->having_fix_field= 0;
|
select_lex->having_fix_field= 0;
|
||||||
DBUG_RETURN(RES_ERROR);
|
DBUG_RETURN(RES_ERROR);
|
||||||
@ -1118,7 +1123,7 @@ Item_in_subselect::row_value_transformer(JOIN *join)
|
|||||||
join->conds can't be fixed after creation, so we do not check
|
join->conds can't be fixed after creation, so we do not check
|
||||||
join->conds->fixed
|
join->conds->fixed
|
||||||
*/
|
*/
|
||||||
if (join->conds->fix_fields(thd, join->tables_list, 0))
|
if (join->conds->fix_fields(thd, 0))
|
||||||
DBUG_RETURN(RES_ERROR);
|
DBUG_RETURN(RES_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1189,8 +1194,7 @@ Item_in_subselect::select_in_like_transformer(JOIN *join, Comp_creator *func)
|
|||||||
|
|
||||||
thd->lex->current_select= up= current->return_after_parsing();
|
thd->lex->current_select= up= current->return_after_parsing();
|
||||||
result= (!left_expr->fixed &&
|
result= (!left_expr->fixed &&
|
||||||
left_expr->fix_fields(thd, up->get_table_list(),
|
left_expr->fix_fields(thd, optimizer->arguments()));
|
||||||
optimizer->arguments()));
|
|
||||||
/* fix_fields can change reference to left_expr, we need reassign it */
|
/* fix_fields can change reference to left_expr, we need reassign it */
|
||||||
left_expr= optimizer->arguments()[0];
|
left_expr= optimizer->arguments()[0];
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ public:
|
|||||||
val_int();
|
val_int();
|
||||||
return null_value;
|
return null_value;
|
||||||
}
|
}
|
||||||
bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref);
|
bool fix_fields(THD *thd, Item **ref);
|
||||||
virtual bool exec();
|
virtual bool exec();
|
||||||
virtual void fix_length_and_dec();
|
virtual void fix_length_and_dec();
|
||||||
table_map used_tables() const;
|
table_map used_tables() const;
|
||||||
@ -119,9 +119,9 @@ public:
|
|||||||
|
|
||||||
friend class select_subselect;
|
friend class select_subselect;
|
||||||
friend class Item_in_optimizer;
|
friend class Item_in_optimizer;
|
||||||
friend bool Item_field::fix_fields(THD *, TABLE_LIST *, Item **);
|
friend bool Item_field::fix_fields(THD *, Item **);
|
||||||
friend bool Item_ref::fix_fields(THD *, TABLE_LIST *, Item **);
|
friend bool Item_ref::fix_fields(THD *, Item **);
|
||||||
friend bool Item_param::fix_fields(THD *, TABLE_LIST *, Item **);
|
friend bool Item_param::fix_fields(THD *, Item **);
|
||||||
friend void mark_select_range_as_dependent(THD*,
|
friend void mark_select_range_as_dependent(THD*,
|
||||||
st_select_lex*, st_select_lex*,
|
st_select_lex*, st_select_lex*,
|
||||||
Field*, Item*, Item_ident*);
|
Field*, Item*, Item_ident*);
|
||||||
|
@ -193,7 +193,7 @@ my_decimal *Item_sum_int::val_decimal(my_decimal *decimal_value)
|
|||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Item_sum_num::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
Item_sum_num::fix_fields(THD *thd, Item **ref)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 0);
|
DBUG_ASSERT(fixed == 0);
|
||||||
|
|
||||||
@ -208,7 +208,7 @@ Item_sum_num::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
|||||||
maybe_null=0;
|
maybe_null=0;
|
||||||
for (uint i=0 ; i < arg_count ; i++)
|
for (uint i=0 ; i < arg_count ; i++)
|
||||||
{
|
{
|
||||||
if (args[i]->fix_fields(thd, tables, args + i) || args[i]->check_cols(1))
|
if (args[i]->fix_fields(thd, args + i) || args[i]->check_cols(1))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
set_if_bigger(decimals, args[i]->decimals);
|
set_if_bigger(decimals, args[i]->decimals);
|
||||||
maybe_null |= args[i]->maybe_null;
|
maybe_null |= args[i]->maybe_null;
|
||||||
@ -253,7 +253,7 @@ Item_sum_hybrid::Item_sum_hybrid(THD *thd, Item_sum_hybrid *item)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
Item_sum_hybrid::fix_fields(THD *thd, Item **ref)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 0);
|
DBUG_ASSERT(fixed == 0);
|
||||||
|
|
||||||
@ -268,7 +268,7 @@ Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
|||||||
|
|
||||||
// 'item' can be changed during fix_fields
|
// 'item' can be changed during fix_fields
|
||||||
if (!item->fixed &&
|
if (!item->fixed &&
|
||||||
item->fix_fields(thd, tables, args) ||
|
item->fix_fields(thd, args) ||
|
||||||
(item= args[0])->check_cols(1))
|
(item= args[0])->check_cols(1))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
decimals=item->decimals;
|
decimals=item->decimals;
|
||||||
@ -2766,11 +2766,12 @@ int dump_leaf_key(byte* key, element_count count __attribute__((unused)),
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Item_func_group_concat::
|
Item_func_group_concat::
|
||||||
Item_func_group_concat(bool distinct_arg, List<Item> *select_list,
|
Item_func_group_concat(Name_resolution_context *context_arg,
|
||||||
|
bool distinct_arg, List<Item> *select_list,
|
||||||
SQL_LIST *order_list, String *separator_arg)
|
SQL_LIST *order_list, String *separator_arg)
|
||||||
:tmp_table_param(0), warning(0),
|
:tmp_table_param(0), warning(0),
|
||||||
separator(separator_arg), tree(0), table(0),
|
separator(separator_arg), tree(0), table(0),
|
||||||
order(0), tables_list(0),
|
order(0), context(context_arg),
|
||||||
arg_count_order(order_list ? order_list->elements : 0),
|
arg_count_order(order_list ? order_list->elements : 0),
|
||||||
arg_count_field(select_list->elements),
|
arg_count_field(select_list->elements),
|
||||||
count_cut_values(0),
|
count_cut_values(0),
|
||||||
@ -2826,7 +2827,7 @@ Item_func_group_concat::Item_func_group_concat(THD *thd,
|
|||||||
tree(item->tree),
|
tree(item->tree),
|
||||||
table(item->table),
|
table(item->table),
|
||||||
order(item->order),
|
order(item->order),
|
||||||
tables_list(item->tables_list),
|
context(item->context),
|
||||||
arg_count_order(item->arg_count_order),
|
arg_count_order(item->arg_count_order),
|
||||||
arg_count_field(item->arg_count_field),
|
arg_count_field(item->arg_count_field),
|
||||||
count_cut_values(item->count_cut_values),
|
count_cut_values(item->count_cut_values),
|
||||||
@ -2946,7 +2947,7 @@ bool Item_func_group_concat::add()
|
|||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
Item_func_group_concat::fix_fields(THD *thd, Item **ref)
|
||||||
{
|
{
|
||||||
uint i; /* for loop variable */
|
uint i; /* for loop variable */
|
||||||
DBUG_ASSERT(fixed == 0);
|
DBUG_ASSERT(fixed == 0);
|
||||||
@ -2968,7 +2969,7 @@ Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
|||||||
for (i=0 ; i < arg_count ; i++)
|
for (i=0 ; i < arg_count ; i++)
|
||||||
{
|
{
|
||||||
if ((!args[i]->fixed &&
|
if ((!args[i]->fixed &&
|
||||||
args[i]->fix_fields(thd, tables, args + i)) ||
|
args[i]->fix_fields(thd, args + i)) ||
|
||||||
args[i]->check_cols(1))
|
args[i]->check_cols(1))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
if (i < arg_count_field)
|
if (i < arg_count_field)
|
||||||
@ -2979,7 +2980,6 @@ Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
|||||||
null_value= 1;
|
null_value= 1;
|
||||||
thd->allow_sum_func= 1;
|
thd->allow_sum_func= 1;
|
||||||
max_length= thd->variables.group_concat_max_len;
|
max_length= thd->variables.group_concat_max_len;
|
||||||
tables_list= tables;
|
|
||||||
fixed= 1;
|
fixed= 1;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@ -3029,7 +3029,7 @@ bool Item_func_group_concat::setup(THD *thd)
|
|||||||
tmp table columns.
|
tmp table columns.
|
||||||
*/
|
*/
|
||||||
if (arg_count_order &&
|
if (arg_count_order &&
|
||||||
setup_order(thd, args, tables_list, list, all_fields, *order))
|
setup_order(thd, args, context->table_list, list, all_fields, *order))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
count_field_types(tmp_table_param,all_fields,0);
|
count_field_types(tmp_table_param,all_fields,0);
|
||||||
|
@ -124,7 +124,7 @@ public:
|
|||||||
Item_sum_num(Item *a, Item* b) :Item_sum(a,b) {}
|
Item_sum_num(Item *a, Item* b) :Item_sum(a,b) {}
|
||||||
Item_sum_num(List<Item> &list) :Item_sum(list) {}
|
Item_sum_num(List<Item> &list) :Item_sum(list) {}
|
||||||
Item_sum_num(THD *thd, Item_sum_num *item) :Item_sum(thd, item) {}
|
Item_sum_num(THD *thd, Item_sum_num *item) :Item_sum(thd, item) {}
|
||||||
bool fix_fields(THD *, TABLE_LIST *, Item **);
|
bool fix_fields(THD *, Item **);
|
||||||
longlong val_int()
|
longlong val_int()
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
@ -543,7 +543,7 @@ protected:
|
|||||||
was_values(TRUE)
|
was_values(TRUE)
|
||||||
{ collation.set(&my_charset_bin); }
|
{ collation.set(&my_charset_bin); }
|
||||||
Item_sum_hybrid(THD *thd, Item_sum_hybrid *item);
|
Item_sum_hybrid(THD *thd, Item_sum_hybrid *item);
|
||||||
bool fix_fields(THD *, TABLE_LIST *, Item **);
|
bool fix_fields(THD *, Item **);
|
||||||
table_map used_tables() const { return used_table_cache; }
|
table_map used_tables() const { return used_table_cache; }
|
||||||
bool const_item() const { return !used_table_cache; }
|
bool const_item() const { return !used_table_cache; }
|
||||||
|
|
||||||
@ -660,18 +660,21 @@ protected:
|
|||||||
udf_handler udf;
|
udf_handler udf;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Item_udf_sum(udf_func *udf_arg) :Item_sum(), udf(udf_arg) { quick_group=0;}
|
Item_udf_sum(udf_func *udf_arg)
|
||||||
|
:Item_sum(), udf(udf_arg)
|
||||||
|
{ quick_group=0; }
|
||||||
Item_udf_sum(udf_func *udf_arg, List<Item> &list)
|
Item_udf_sum(udf_func *udf_arg, List<Item> &list)
|
||||||
:Item_sum(list), udf(udf_arg)
|
:Item_sum(list), udf(udf_arg)
|
||||||
{ quick_group=0;}
|
{ quick_group=0;}
|
||||||
Item_udf_sum(THD *thd, Item_udf_sum *item)
|
Item_udf_sum(THD *thd, Item_udf_sum *item)
|
||||||
:Item_sum(thd, item), udf(item->udf) { udf.not_original= TRUE; }
|
:Item_sum(thd, item), udf(item->udf)
|
||||||
|
{ udf.not_original= TRUE; }
|
||||||
const char *func_name() const { return udf.name(); }
|
const char *func_name() const { return udf.name(); }
|
||||||
bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
bool fix_fields(THD *thd, Item **ref)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 0);
|
DBUG_ASSERT(fixed == 0);
|
||||||
fixed= 1;
|
fixed= 1;
|
||||||
return udf.fix_fields(thd,tables,this,this->arg_count,this->args);
|
return udf.fix_fields(thd, this, this->arg_count, this->args);
|
||||||
}
|
}
|
||||||
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
|
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
|
||||||
virtual bool have_field_update(void) const { return 0; }
|
virtual bool have_field_update(void) const { return 0; }
|
||||||
@ -688,7 +691,8 @@ public:
|
|||||||
class Item_sum_udf_float :public Item_udf_sum
|
class Item_sum_udf_float :public Item_udf_sum
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Item_sum_udf_float(udf_func *udf_arg) :Item_udf_sum(udf_arg) {}
|
Item_sum_udf_float(udf_func *udf_arg)
|
||||||
|
:Item_udf_sum(udf_arg) {}
|
||||||
Item_sum_udf_float(udf_func *udf_arg, List<Item> &list)
|
Item_sum_udf_float(udf_func *udf_arg, List<Item> &list)
|
||||||
:Item_udf_sum(udf_arg, list) {}
|
:Item_udf_sum(udf_arg, list) {}
|
||||||
Item_sum_udf_float(THD *thd, Item_sum_udf_float *item)
|
Item_sum_udf_float(THD *thd, Item_sum_udf_float *item)
|
||||||
@ -709,7 +713,8 @@ class Item_sum_udf_float :public Item_udf_sum
|
|||||||
class Item_sum_udf_int :public Item_udf_sum
|
class Item_sum_udf_int :public Item_udf_sum
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Item_sum_udf_int(udf_func *udf_arg) :Item_udf_sum(udf_arg) {}
|
Item_sum_udf_int(udf_func *udf_arg)
|
||||||
|
:Item_udf_sum(udf_arg) {}
|
||||||
Item_sum_udf_int(udf_func *udf_arg, List<Item> &list)
|
Item_sum_udf_int(udf_func *udf_arg, List<Item> &list)
|
||||||
:Item_udf_sum(udf_arg, list) {}
|
:Item_udf_sum(udf_arg, list) {}
|
||||||
Item_sum_udf_int(THD *thd, Item_sum_udf_int *item)
|
Item_sum_udf_int(THD *thd, Item_sum_udf_int *item)
|
||||||
@ -728,7 +733,8 @@ public:
|
|||||||
class Item_sum_udf_str :public Item_udf_sum
|
class Item_sum_udf_str :public Item_udf_sum
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Item_sum_udf_str(udf_func *udf_arg) :Item_udf_sum(udf_arg) {}
|
Item_sum_udf_str(udf_func *udf_arg)
|
||||||
|
:Item_udf_sum(udf_arg) {}
|
||||||
Item_sum_udf_str(udf_func *udf_arg, List<Item> &list)
|
Item_sum_udf_str(udf_func *udf_arg, List<Item> &list)
|
||||||
:Item_udf_sum(udf_arg,list) {}
|
:Item_udf_sum(udf_arg,list) {}
|
||||||
Item_sum_udf_str(THD *thd, Item_sum_udf_str *item)
|
Item_sum_udf_str(THD *thd, Item_sum_udf_str *item)
|
||||||
@ -766,7 +772,8 @@ public:
|
|||||||
class Item_sum_udf_decimal :public Item_udf_sum
|
class Item_sum_udf_decimal :public Item_udf_sum
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Item_sum_udf_decimal(udf_func *udf_arg) :Item_udf_sum(udf_arg) {}
|
Item_sum_udf_decimal(udf_func *udf_arg)
|
||||||
|
:Item_udf_sum(udf_arg) {}
|
||||||
Item_sum_udf_decimal(udf_func *udf_arg, List<Item> &list)
|
Item_sum_udf_decimal(udf_func *udf_arg, List<Item> &list)
|
||||||
:Item_udf_sum(udf_arg, list) {}
|
:Item_udf_sum(udf_arg, list) {}
|
||||||
Item_sum_udf_decimal(THD *thd, Item_sum_udf_decimal *item)
|
Item_sum_udf_decimal(THD *thd, Item_sum_udf_decimal *item)
|
||||||
@ -785,7 +792,8 @@ public:
|
|||||||
class Item_sum_udf_float :public Item_sum_num
|
class Item_sum_udf_float :public Item_sum_num
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Item_sum_udf_float(udf_func *udf_arg) :Item_sum_num() {}
|
Item_sum_udf_float(udf_func *udf_arg)
|
||||||
|
:Item_sum_num() {}
|
||||||
Item_sum_udf_float(udf_func *udf_arg, List<Item> &list) :Item_sum_num() {}
|
Item_sum_udf_float(udf_func *udf_arg, List<Item> &list) :Item_sum_num() {}
|
||||||
Item_sum_udf_float(THD *thd, Item_sum_udf_float *item)
|
Item_sum_udf_float(THD *thd, Item_sum_udf_float *item)
|
||||||
:Item_sum_num(thd, item) {}
|
:Item_sum_num(thd, item) {}
|
||||||
@ -800,7 +808,8 @@ class Item_sum_udf_float :public Item_sum_num
|
|||||||
class Item_sum_udf_int :public Item_sum_num
|
class Item_sum_udf_int :public Item_sum_num
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Item_sum_udf_int(udf_func *udf_arg) :Item_sum_num() {}
|
Item_sum_udf_int(udf_func *udf_arg)
|
||||||
|
:Item_sum_num() {}
|
||||||
Item_sum_udf_int(udf_func *udf_arg, List<Item> &list) :Item_sum_num() {}
|
Item_sum_udf_int(udf_func *udf_arg, List<Item> &list) :Item_sum_num() {}
|
||||||
Item_sum_udf_int(THD *thd, Item_sum_udf_int *item)
|
Item_sum_udf_int(THD *thd, Item_sum_udf_int *item)
|
||||||
:Item_sum_num(thd, item) {}
|
:Item_sum_num(thd, item) {}
|
||||||
@ -816,8 +825,10 @@ public:
|
|||||||
class Item_sum_udf_decimal :public Item_sum_num
|
class Item_sum_udf_decimal :public Item_sum_num
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Item_sum_udf_decimal(udf_func *udf_arg) :Item_sum_num() {}
|
Item_sum_udf_decimal(udf_func *udf_arg)
|
||||||
Item_sum_udf_decimal(udf_func *udf_arg, List<Item> &list) :Item_sum_num() {}
|
:Item_sum_num() {}
|
||||||
|
Item_sum_udf_decimal(udf_func *udf_arg, List<Item> &list)
|
||||||
|
:Item_sum_num() {}
|
||||||
Item_sum_udf_decimal(THD *thd, Item_sum_udf_float *item)
|
Item_sum_udf_decimal(THD *thd, Item_sum_udf_float *item)
|
||||||
:Item_sum_num(thd, item) {}
|
:Item_sum_num(thd, item) {}
|
||||||
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
|
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
|
||||||
@ -832,8 +843,10 @@ class Item_sum_udf_decimal :public Item_sum_num
|
|||||||
class Item_sum_udf_str :public Item_sum_num
|
class Item_sum_udf_str :public Item_sum_num
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Item_sum_udf_str(udf_func *udf_arg) :Item_sum_num() {}
|
Item_sum_udf_str(udf_func *udf_arg)
|
||||||
Item_sum_udf_str(udf_func *udf_arg, List<Item> &list) :Item_sum_num() {}
|
:Item_sum_num() {}
|
||||||
|
Item_sum_udf_str(udf_func *udf_arg, List<Item> &list)
|
||||||
|
:Item_sum_num() {}
|
||||||
Item_sum_udf_str(THD *thd, Item_sum_udf_str *item)
|
Item_sum_udf_str(THD *thd, Item_sum_udf_str *item)
|
||||||
:Item_sum_num(thd, item) {}
|
:Item_sum_num(thd, item) {}
|
||||||
String *val_str(String *)
|
String *val_str(String *)
|
||||||
@ -862,7 +875,7 @@ class Item_func_group_concat : public Item_sum
|
|||||||
TREE *tree;
|
TREE *tree;
|
||||||
TABLE *table;
|
TABLE *table;
|
||||||
ORDER **order;
|
ORDER **order;
|
||||||
TABLE_LIST *tables_list;
|
Name_resolution_context *context;
|
||||||
uint arg_count_order; // total count of ORDER BY items
|
uint arg_count_order; // total count of ORDER BY items
|
||||||
uint arg_count_field; // count of arguments
|
uint arg_count_field; // count of arguments
|
||||||
uint count_cut_values;
|
uint count_cut_values;
|
||||||
@ -887,7 +900,8 @@ class Item_func_group_concat : public Item_sum
|
|||||||
Item_func_group_concat *group_concat_item);
|
Item_func_group_concat *group_concat_item);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Item_func_group_concat(bool is_distinct,List<Item> *is_select,
|
Item_func_group_concat(Name_resolution_context *context_arg,
|
||||||
|
bool is_distinct, List<Item> *is_select,
|
||||||
SQL_LIST *is_order, String *is_separator);
|
SQL_LIST *is_order, String *is_separator);
|
||||||
|
|
||||||
Item_func_group_concat(THD *thd, Item_func_group_concat *item);
|
Item_func_group_concat(THD *thd, Item_func_group_concat *item);
|
||||||
@ -901,7 +915,7 @@ public:
|
|||||||
bool add();
|
bool add();
|
||||||
void reset_field() {} // not used
|
void reset_field() {} // not used
|
||||||
void update_field() {} // not used
|
void update_field() {} // not used
|
||||||
bool fix_fields(THD *, TABLE_LIST *, Item **);
|
bool fix_fields(THD *,Item **);
|
||||||
bool setup(THD *thd);
|
bool setup(THD *thd);
|
||||||
void make_unique();
|
void make_unique();
|
||||||
double val_real()
|
double val_real()
|
||||||
@ -927,4 +941,6 @@ public:
|
|||||||
Item *copy_or_same(THD* thd);
|
Item *copy_or_same(THD* thd);
|
||||||
void no_rows_in_result() {}
|
void no_rows_in_result() {}
|
||||||
void print(String *str);
|
void print(String *str);
|
||||||
|
virtual bool change_context_processor(byte *cntx)
|
||||||
|
{ context= (Name_resolution_context *)cntx; return FALSE; }
|
||||||
};
|
};
|
||||||
|
@ -1753,10 +1753,10 @@ void Item_func_convert_tz::fix_length_and_dec()
|
|||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Item_func_convert_tz::fix_fields(THD *thd_arg, TABLE_LIST *tables_arg, Item **ref)
|
Item_func_convert_tz::fix_fields(THD *thd_arg, Item **ref)
|
||||||
{
|
{
|
||||||
String str;
|
String str;
|
||||||
if (Item_date_func::fix_fields(thd_arg, tables_arg, ref))
|
if (Item_date_func::fix_fields(thd_arg, ref))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
tz_tables= thd_arg->lex->time_zone_tables_used;
|
tz_tables= thd_arg->lex->time_zone_tables_used;
|
||||||
|
@ -561,7 +561,7 @@ class Item_func_convert_tz :public Item_date_func
|
|||||||
double val_real() { return (double) val_int(); }
|
double val_real() { return (double) val_int(); }
|
||||||
String *val_str(String *str);
|
String *val_str(String *str);
|
||||||
const char *func_name() const { return "convert_tz"; }
|
const char *func_name() const { return "convert_tz"; }
|
||||||
bool fix_fields(THD *, struct st_table_list *, Item **);
|
bool fix_fields(THD *, Item **);
|
||||||
void fix_length_and_dec();
|
void fix_length_and_dec();
|
||||||
bool get_date(TIME *res, uint fuzzy_date);
|
bool get_date(TIME *res, uint fuzzy_date);
|
||||||
void cleanup();
|
void cleanup();
|
||||||
|
@ -47,7 +47,7 @@ public:
|
|||||||
bool add() { return 0; }
|
bool add() { return 0; }
|
||||||
void reset_field() {}
|
void reset_field() {}
|
||||||
void update_field() {}
|
void update_field() {}
|
||||||
bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
|
bool fix_fields(THD *thd, Item **ref)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 0);
|
DBUG_ASSERT(fixed == 0);
|
||||||
fixed= 1;
|
fixed= 1;
|
||||||
|
@ -2618,13 +2618,15 @@ void Load_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_ev
|
|||||||
|
|
||||||
#ifndef MYSQL_CLIENT
|
#ifndef MYSQL_CLIENT
|
||||||
void Load_log_event::set_fields(const char* affected_db,
|
void Load_log_event::set_fields(const char* affected_db,
|
||||||
List<Item> &field_list)
|
List<Item> &field_list,
|
||||||
|
Name_resolution_context *context)
|
||||||
{
|
{
|
||||||
uint i;
|
uint i;
|
||||||
const char* field = fields;
|
const char* field = fields;
|
||||||
for (i= 0; i < num_fields; i++)
|
for (i= 0; i < num_fields; i++)
|
||||||
{
|
{
|
||||||
field_list.push_back(new Item_field(affected_db, table_name, field));
|
field_list.push_back(new Item_field(context,
|
||||||
|
affected_db, table_name, field));
|
||||||
field+= field_lens[i] + 1;
|
field+= field_lens[i] + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2789,7 +2791,8 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
|
|||||||
|
|
||||||
ex.skip_lines = skip_lines;
|
ex.skip_lines = skip_lines;
|
||||||
List<Item> field_list;
|
List<Item> field_list;
|
||||||
set_fields(thd->db,field_list);
|
thd->main_lex.select_lex.context.resolve_in_table_list_only(&tables);
|
||||||
|
set_fields(thd->db, field_list, &thd->main_lex.select_lex.context);
|
||||||
thd->variables.pseudo_thread_id= thread_id;
|
thd->variables.pseudo_thread_id= thread_id;
|
||||||
List<Item> set_fields;
|
List<Item> set_fields;
|
||||||
if (net)
|
if (net)
|
||||||
@ -3617,7 +3620,7 @@ int User_var_log_event::exec_event(struct st_relay_log_info* rli)
|
|||||||
Item_func_set_user_var can't substitute something else on its place =>
|
Item_func_set_user_var can't substitute something else on its place =>
|
||||||
0 can be passed as last argument (reference on item)
|
0 can be passed as last argument (reference on item)
|
||||||
*/
|
*/
|
||||||
e.fix_fields(thd, 0, 0);
|
e.fix_fields(thd, 0);
|
||||||
/*
|
/*
|
||||||
A variable can just be considered as a table with
|
A variable can just be considered as a table with
|
||||||
a single record and with a single column. Thus, like
|
a single record and with a single column. Thus, like
|
||||||
|
@ -877,7 +877,8 @@ public:
|
|||||||
const char* table_name_arg,
|
const char* table_name_arg,
|
||||||
List<Item>& fields_arg, enum enum_duplicates handle_dup, bool ignore,
|
List<Item>& fields_arg, enum enum_duplicates handle_dup, bool ignore,
|
||||||
bool using_trans);
|
bool using_trans);
|
||||||
void set_fields(const char* db, List<Item> &fields_arg);
|
void set_fields(const char* db, List<Item> &fields_arg,
|
||||||
|
Name_resolution_context *context);
|
||||||
const char* get_db() { return db; }
|
const char* get_db() { return db; }
|
||||||
#ifdef HAVE_REPLICATION
|
#ifdef HAVE_REPLICATION
|
||||||
void pack_info(Protocol* protocol);
|
void pack_info(Protocol* protocol);
|
||||||
|
@ -726,7 +726,8 @@ bool mysql_insert(THD *thd,TABLE_LIST *table,List<Item> &fields,
|
|||||||
List<List_item> &values, List<Item> &update_fields,
|
List<List_item> &values, List<Item> &update_fields,
|
||||||
List<Item> &update_values, enum_duplicates flag,
|
List<Item> &update_values, enum_duplicates flag,
|
||||||
bool ignore);
|
bool ignore);
|
||||||
int check_that_all_fields_are_given_values(THD *thd, TABLE *entry);
|
int check_that_all_fields_are_given_values(THD *thd, TABLE *entry,
|
||||||
|
TABLE_LIST *table_list);
|
||||||
bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds);
|
bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds);
|
||||||
bool mysql_delete(THD *thd, TABLE_LIST *table, COND *conds, SQL_LIST *order,
|
bool mysql_delete(THD *thd, TABLE_LIST *table, COND *conds, SQL_LIST *order,
|
||||||
ha_rows rows, ulong options);
|
ha_rows rows, ulong options);
|
||||||
@ -893,16 +894,29 @@ Item ** find_item_in_list(Item *item, List<Item> &items, uint *counter,
|
|||||||
bool *unaliased);
|
bool *unaliased);
|
||||||
bool get_key_map_from_key_list(key_map *map, TABLE *table,
|
bool get_key_map_from_key_list(key_map *map, TABLE *table,
|
||||||
List<String> *index_list);
|
List<String> *index_list);
|
||||||
bool insert_fields(THD *thd,TABLE_LIST *tables,
|
bool insert_fields(THD *thd, Name_resolution_context *context,
|
||||||
const char *db_name, const char *table_name,
|
const char *db_name, const char *table_name,
|
||||||
List_iterator<Item> *it, bool any_privileges);
|
List_iterator<Item> *it, bool any_privileges);
|
||||||
bool setup_tables(THD *thd, TABLE_LIST *tables, Item **conds,
|
bool setup_tables(THD *thd, Name_resolution_context *context,
|
||||||
|
TABLE_LIST *tables, Item **conds,
|
||||||
TABLE_LIST **leaves, bool select_insert);
|
TABLE_LIST **leaves, bool select_insert);
|
||||||
int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
|
int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
|
||||||
List<Item> *sum_func_list, uint wild_num);
|
List<Item> *sum_func_list, uint wild_num);
|
||||||
bool setup_fields(THD *thd, Item** ref_pointer_array, TABLE_LIST *tables,
|
bool setup_fields(THD *thd, Item** ref_pointer_array,
|
||||||
List<Item> &item, bool set_query_id,
|
List<Item> &item, bool set_query_id,
|
||||||
List<Item> *sum_func_list, bool allow_sum_func);
|
List<Item> *sum_func_list, bool allow_sum_func);
|
||||||
|
inline bool setup_fields_with_no_wrap(THD *thd, Item **ref_pointer_array,
|
||||||
|
List<Item> &item, bool set_query_id,
|
||||||
|
List<Item> *sum_func_list,
|
||||||
|
bool allow_sum_func)
|
||||||
|
{
|
||||||
|
bool res;
|
||||||
|
thd->lex->select_lex.no_wrap_view_item= TRUE;
|
||||||
|
res= setup_fields(thd, ref_pointer_array, item, set_query_id, sum_func_list,
|
||||||
|
allow_sum_func);
|
||||||
|
thd->lex->select_lex.no_wrap_view_item= FALSE;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
|
int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
|
||||||
COND **conds);
|
COND **conds);
|
||||||
int setup_ftfuncs(SELECT_LEX* select);
|
int setup_ftfuncs(SELECT_LEX* select);
|
||||||
|
@ -2983,7 +2983,7 @@ int set_var::check(THD *thd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((!value->fixed &&
|
if ((!value->fixed &&
|
||||||
value->fix_fields(thd, 0, &value)) || value->check_cols(1))
|
value->fix_fields(thd, &value)) || value->check_cols(1))
|
||||||
return -1;
|
return -1;
|
||||||
if (var->check_update_type(value->result_type()))
|
if (var->check_update_type(value->result_type()))
|
||||||
{
|
{
|
||||||
@ -3017,7 +3017,7 @@ int set_var::light_check(THD *thd)
|
|||||||
if (type == OPT_GLOBAL && check_global_access(thd, SUPER_ACL))
|
if (type == OPT_GLOBAL && check_global_access(thd, SUPER_ACL))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (value && ((!value->fixed && value->fix_fields(thd, 0, &value)) ||
|
if (value && ((!value->fixed && value->fix_fields(thd, &value)) ||
|
||||||
value->check_cols(1)))
|
value->check_cols(1)))
|
||||||
return -1;
|
return -1;
|
||||||
return 0;
|
return 0;
|
||||||
@ -3046,7 +3046,7 @@ int set_var_user::check(THD *thd)
|
|||||||
Item_func_set_user_var can't substitute something else on its place =>
|
Item_func_set_user_var can't substitute something else on its place =>
|
||||||
0 can be passed as last argument (reference on item)
|
0 can be passed as last argument (reference on item)
|
||||||
*/
|
*/
|
||||||
return (user_var_item->fix_fields(thd, 0, (Item**) 0) ||
|
return (user_var_item->fix_fields(thd, (Item**) 0) ||
|
||||||
user_var_item->check()) ? -1 : 0;
|
user_var_item->check()) ? -1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3069,7 +3069,7 @@ int set_var_user::light_check(THD *thd)
|
|||||||
Item_func_set_user_var can't substitute something else on its place =>
|
Item_func_set_user_var can't substitute something else on its place =>
|
||||||
0 can be passed as last argument (reference on item)
|
0 can be passed as last argument (reference on item)
|
||||||
*/
|
*/
|
||||||
return (user_var_item->fix_fields(thd, 0, (Item**) 0));
|
return (user_var_item->fix_fields(thd, (Item**) 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -5358,3 +5358,5 @@ ER_STMT_HAS_NO_OPEN_CURSOR
|
|||||||
eng "The statement (%lu) has no open cursor."
|
eng "The statement (%lu) has no open cursor."
|
||||||
ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
|
ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
|
||||||
eng "Explicit or implicit commit is not allowed in stored function or trigger."
|
eng "Explicit or implicit commit is not allowed in stored function or trigger."
|
||||||
|
ER_NO_DEFAULT_FOR_VIEW_FIELD
|
||||||
|
eng "Field of view '%-.64s.%-.64s' underlying table doesn't have a default value"
|
||||||
|
10
sql/sp.cc
10
sql/sp.cc
@ -676,14 +676,18 @@ db_show_routine_status(THD *thd, int type, const char *wild)
|
|||||||
|
|
||||||
tables is not VIEW for sure => we can pass 0 as condition
|
tables is not VIEW for sure => we can pass 0 as condition
|
||||||
*/
|
*/
|
||||||
setup_tables(thd, &tables, 0, &leaves, FALSE);
|
thd->lex->select_lex.context.resolve_in_table_list_only(&tables);
|
||||||
|
setup_tables(thd, &thd->lex->select_lex.context,
|
||||||
|
&tables, 0, &leaves, FALSE);
|
||||||
for (used_field= &used_fields[0];
|
for (used_field= &used_fields[0];
|
||||||
used_field->field_name;
|
used_field->field_name;
|
||||||
used_field++)
|
used_field++)
|
||||||
{
|
{
|
||||||
Item_field *field= new Item_field("mysql", "proc",
|
Item_field *field= new Item_field(&thd->lex->select_lex.context,
|
||||||
|
"mysql", "proc",
|
||||||
used_field->field_name);
|
used_field->field_name);
|
||||||
if (!(used_field->field= find_field_in_tables(thd, field, &tables,
|
if (!field ||
|
||||||
|
!(used_field->field= find_field_in_tables(thd, field, &tables,
|
||||||
0, REPORT_ALL_ERRORS, 1)))
|
0, REPORT_ALL_ERRORS, 1)))
|
||||||
{
|
{
|
||||||
res= SP_INTERNAL_ERROR;
|
res= SP_INTERNAL_ERROR;
|
||||||
|
@ -117,7 +117,7 @@ sp_prepare_func_item(THD* thd, Item **it_addr)
|
|||||||
DBUG_ENTER("sp_prepare_func_item");
|
DBUG_ENTER("sp_prepare_func_item");
|
||||||
it_addr= it->this_item_addr(thd, it_addr);
|
it_addr= it->this_item_addr(thd, it_addr);
|
||||||
|
|
||||||
if (!it->fixed && (*it_addr)->fix_fields(thd, 0, it_addr))
|
if (!it->fixed && (*it_addr)->fix_fields(thd, it_addr))
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info", ("fix_fields() failed"));
|
DBUG_PRINT("info", ("fix_fields() failed"));
|
||||||
DBUG_RETURN(NULL);
|
DBUG_RETURN(NULL);
|
||||||
@ -962,7 +962,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
|
|||||||
we do not check suv->fixed, because it can't be fixed after
|
we do not check suv->fixed, because it can't be fixed after
|
||||||
creation
|
creation
|
||||||
*/
|
*/
|
||||||
suv->fix_fields(thd, NULL, &item);
|
suv->fix_fields(thd, &item);
|
||||||
suv->fix_length_and_dec();
|
suv->fix_length_and_dec();
|
||||||
suv->check();
|
suv->check();
|
||||||
suv->update();
|
suv->update();
|
||||||
@ -1579,8 +1579,8 @@ sp_instr_set_trigger_field::execute(THD *thd, uint *nextp)
|
|||||||
|
|
||||||
DBUG_ENTER("sp_instr_set_trigger_field::execute");
|
DBUG_ENTER("sp_instr_set_trigger_field::execute");
|
||||||
/* QQ: Still unsure what should we return in case of error 1 or -1 ? */
|
/* QQ: Still unsure what should we return in case of error 1 or -1 ? */
|
||||||
if (!value->fixed && value->fix_fields(thd, 0, &value) ||
|
if (!value->fixed && value->fix_fields(thd, &value) ||
|
||||||
trigger_field->fix_fields(thd, 0, 0) ||
|
trigger_field->fix_fields(thd, 0) ||
|
||||||
(value->save_in_field(trigger_field->field, 0) < 0))
|
(value->save_in_field(trigger_field->field, 0) < 0))
|
||||||
res= -1;
|
res= -1;
|
||||||
*nextp= m_ip + 1;
|
*nextp= m_ip + 1;
|
||||||
|
@ -470,10 +470,11 @@ class sp_instr_set_trigger_field : public sp_instr
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
sp_instr_set_trigger_field(uint ip, sp_pcontext *ctx,
|
sp_instr_set_trigger_field(Name_resolution_context *context_arg,
|
||||||
|
uint ip, sp_pcontext *ctx,
|
||||||
Item_trigger_field *trg_fld, Item *val)
|
Item_trigger_field *trg_fld, Item *val)
|
||||||
: sp_instr(ip, ctx),
|
: sp_instr(ip, ctx),
|
||||||
trigger_field(trg_fld),
|
trigger_field(context_arg, trg_fld),
|
||||||
value(val)
|
value(val)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
173
sql/sql_base.cc
173
sql/sql_base.cc
@ -2439,21 +2439,19 @@ find_field_in_table(THD *thd, TABLE_LIST *table_list,
|
|||||||
table_list->alias, name, item_name, (ulong) ref));
|
table_list->alias, name, item_name, (ulong) ref));
|
||||||
if (table_list->field_translation)
|
if (table_list->field_translation)
|
||||||
{
|
{
|
||||||
uint num;
|
Field_iterator_view field_it;
|
||||||
if (table_list->schema_table_reformed)
|
field_it.set(table_list);
|
||||||
|
DBUG_ASSERT(table_list->schema_table_reformed ||
|
||||||
|
(ref != 0 && table_list->view != 0));
|
||||||
|
for (; !field_it.end_of_fields(); field_it.next())
|
||||||
{
|
{
|
||||||
num= thd->lex->current_select->item_list.elements;
|
if (!my_strcasecmp(system_charset_info, field_it.name(), name))
|
||||||
|
{
|
||||||
|
Item *item= field_it.create_item(thd);
|
||||||
|
if (!item)
|
||||||
|
{
|
||||||
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
DBUG_ASSERT(ref != 0 && table_list->view != 0);
|
|
||||||
num= table_list->view->select_lex.item_list.elements;
|
|
||||||
}
|
|
||||||
Field_translator *trans= table_list->field_translation;
|
|
||||||
for (uint i= 0; i < num; i ++)
|
|
||||||
{
|
|
||||||
if (!my_strcasecmp(system_charset_info, trans[i].name, name))
|
|
||||||
{
|
|
||||||
if (table_list->schema_table_reformed)
|
if (table_list->schema_table_reformed)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -2462,7 +2460,7 @@ find_field_in_table(THD *thd, TABLE_LIST *table_list,
|
|||||||
So we can return ->field. It is used only for
|
So we can return ->field. It is used only for
|
||||||
'show & where' commands.
|
'show & where' commands.
|
||||||
*/
|
*/
|
||||||
DBUG_RETURN(((Item_field*) (trans[i].item))->field);
|
DBUG_RETURN(((Item_field*) (field_it.item()))->field);
|
||||||
}
|
}
|
||||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||||
if (check_grants_view &&
|
if (check_grants_view &&
|
||||||
@ -2472,26 +2470,10 @@ find_field_in_table(THD *thd, TABLE_LIST *table_list,
|
|||||||
name, length))
|
name, length))
|
||||||
DBUG_RETURN(WRONG_GRANT);
|
DBUG_RETURN(WRONG_GRANT);
|
||||||
#endif
|
#endif
|
||||||
if (thd->lex->current_select->no_wrap_view_item)
|
|
||||||
{
|
|
||||||
if (register_tree_change)
|
if (register_tree_change)
|
||||||
thd->change_item_tree(ref, trans[i].item);
|
thd->change_item_tree(ref, item);
|
||||||
else
|
else
|
||||||
*ref= trans[i].item;
|
*ref= item;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Item_ref *item_ref= new Item_ref(&trans[i].item,
|
|
||||||
table_list->view_name.str,
|
|
||||||
item_name);
|
|
||||||
/* as far as Item_ref have defined reference it do not need tables */
|
|
||||||
if (register_tree_change && item_ref)
|
|
||||||
thd->change_item_tree(ref, item_ref);
|
|
||||||
else if (item_ref)
|
|
||||||
*ref= item_ref;
|
|
||||||
if (!(*ref)->fixed)
|
|
||||||
(*ref)->fix_fields(thd, 0, ref);
|
|
||||||
}
|
|
||||||
DBUG_RETURN((Field*) view_ref_found);
|
DBUG_RETURN((Field*) view_ref_found);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3066,7 +3048,8 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
|
|||||||
*/
|
*/
|
||||||
it.replace(new Item_int("Not_used", (longlong) 1, 21));
|
it.replace(new Item_int("Not_used", (longlong) 1, 21));
|
||||||
}
|
}
|
||||||
else if (insert_fields(thd,tables,((Item_field*) item)->db_name,
|
else if (insert_fields(thd, ((Item_field*) item)->context,
|
||||||
|
((Item_field*) item)->db_name,
|
||||||
((Item_field*) item)->table_name, &it,
|
((Item_field*) item)->table_name, &it,
|
||||||
any_privileges))
|
any_privileges))
|
||||||
{
|
{
|
||||||
@ -3102,7 +3085,7 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
|
|||||||
** Check that all given fields exists and fill struct with current data
|
** Check that all given fields exists and fill struct with current data
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
bool setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
|
bool setup_fields(THD *thd, Item **ref_pointer_array,
|
||||||
List<Item> &fields, bool set_query_id,
|
List<Item> &fields, bool set_query_id,
|
||||||
List<Item> *sum_func_list, bool allow_sum_func)
|
List<Item> *sum_func_list, bool allow_sum_func)
|
||||||
{
|
{
|
||||||
@ -3131,7 +3114,7 @@ bool setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
|
|||||||
Item **ref= ref_pointer_array;
|
Item **ref= ref_pointer_array;
|
||||||
while ((item= it++))
|
while ((item= it++))
|
||||||
{
|
{
|
||||||
if (!item->fixed && item->fix_fields(thd, tables, it.ref()) ||
|
if (!item->fixed && item->fix_fields(thd, it.ref()) ||
|
||||||
(item= *(it.ref()))->check_cols(1))
|
(item= *(it.ref()))->check_cols(1))
|
||||||
{
|
{
|
||||||
DBUG_RETURN(TRUE); /* purecov: inspected */
|
DBUG_RETURN(TRUE); /* purecov: inspected */
|
||||||
@ -3181,6 +3164,7 @@ TABLE_LIST **make_leaves_list(TABLE_LIST **list, TABLE_LIST *tables)
|
|||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
setup_tables()
|
setup_tables()
|
||||||
thd Thread handler
|
thd Thread handler
|
||||||
|
context name resolution contest to setup table list there
|
||||||
tables Table list
|
tables Table list
|
||||||
conds Condition of current SELECT (can be changed by VIEW)
|
conds Condition of current SELECT (can be changed by VIEW)
|
||||||
leaves List of join table leaves list
|
leaves List of join table leaves list
|
||||||
@ -3200,11 +3184,15 @@ TABLE_LIST **make_leaves_list(TABLE_LIST **list, TABLE_LIST *tables)
|
|||||||
TRUE error
|
TRUE error
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool setup_tables(THD *thd, TABLE_LIST *tables, Item **conds,
|
bool setup_tables(THD *thd, Name_resolution_context *context,
|
||||||
|
TABLE_LIST *tables, Item **conds,
|
||||||
TABLE_LIST **leaves, bool select_insert)
|
TABLE_LIST **leaves, bool select_insert)
|
||||||
{
|
{
|
||||||
uint tablenr= 0;
|
uint tablenr= 0;
|
||||||
DBUG_ENTER("setup_tables");
|
DBUG_ENTER("setup_tables");
|
||||||
|
|
||||||
|
context->table_list= tables;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
this is used for INSERT ... SELECT.
|
this is used for INSERT ... SELECT.
|
||||||
For select we setup tables except first (and its underlying tables)
|
For select we setup tables except first (and its underlying tables)
|
||||||
@ -3259,11 +3247,22 @@ bool setup_tables(THD *thd, TABLE_LIST *tables, Item **conds,
|
|||||||
table_list;
|
table_list;
|
||||||
table_list= table_list->next_local)
|
table_list= table_list->next_local)
|
||||||
{
|
{
|
||||||
if (table_list->ancestor &&
|
if (table_list->ancestor)
|
||||||
table_list->setup_ancestor(thd, conds,
|
{
|
||||||
table_list->effective_with_check))
|
DBUG_ASSERT(table_list->view);
|
||||||
|
Query_arena *arena= thd->current_arena, backup;
|
||||||
|
bool res;
|
||||||
|
if (arena->is_conventional())
|
||||||
|
arena= 0; // For easier test
|
||||||
|
else
|
||||||
|
thd->set_n_backup_item_arena(arena, &backup);
|
||||||
|
res= table_list->setup_ancestor(thd);
|
||||||
|
if (arena)
|
||||||
|
thd->restore_backup_item_arena(arena, &backup);
|
||||||
|
if (res)
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3314,7 +3313,7 @@ bool get_key_map_from_key_list(key_map *map, TABLE *table,
|
|||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
insert_fields()
|
insert_fields()
|
||||||
thd Thread handler
|
thd Thread handler
|
||||||
tables List of tables
|
context Context for name resolution
|
||||||
db_name Database name in case of 'database_name.table_name.*'
|
db_name Database name in case of 'database_name.table_name.*'
|
||||||
table_name Table name in case of 'table_name.*'
|
table_name Table name in case of 'table_name.*'
|
||||||
it Pointer to '*'
|
it Pointer to '*'
|
||||||
@ -3328,7 +3327,7 @@ bool get_key_map_from_key_list(key_map *map, TABLE *table,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
bool
|
bool
|
||||||
insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
|
insert_fields(THD *thd, Name_resolution_context *context, const char *db_name,
|
||||||
const char *table_name, List_iterator<Item> *it,
|
const char *table_name, List_iterator<Item> *it,
|
||||||
bool any_privileges)
|
bool any_privileges)
|
||||||
{
|
{
|
||||||
@ -3352,7 +3351,9 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
found= 0;
|
found= 0;
|
||||||
for (; tables; tables= tables->next_local)
|
for (TABLE_LIST *tables= context->table_list;
|
||||||
|
tables;
|
||||||
|
tables= tables->next_local)
|
||||||
{
|
{
|
||||||
Field_iterator *iterator;
|
Field_iterator *iterator;
|
||||||
TABLE_LIST *natural_join_table;
|
TABLE_LIST *natural_join_table;
|
||||||
@ -3361,7 +3362,6 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
|
|||||||
TABLE_LIST *last;
|
TABLE_LIST *last;
|
||||||
TABLE_LIST *embedding;
|
TABLE_LIST *embedding;
|
||||||
TABLE *table= tables->table;
|
TABLE *table= tables->table;
|
||||||
bool alias_used= 0;
|
|
||||||
|
|
||||||
if (!table_name || (!my_strcasecmp(table_alias_charset, table_name,
|
if (!table_name || (!my_strcasecmp(table_alias_charset, table_name,
|
||||||
tables->alias) &&
|
tables->alias) &&
|
||||||
@ -3395,16 +3395,6 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (table)
|
|
||||||
thd->used_tables|= table->map;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
view_iter.set(tables);
|
|
||||||
for (; !view_iter.end_of_fields(); view_iter.next())
|
|
||||||
{
|
|
||||||
thd->used_tables|= view_iter.item(thd)->used_tables();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
natural_join_table= 0;
|
natural_join_table= 0;
|
||||||
last= embedded= tables;
|
last= embedded= tables;
|
||||||
|
|
||||||
@ -3435,8 +3425,6 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
|
|||||||
{
|
{
|
||||||
iterator= &view_iter;
|
iterator= &view_iter;
|
||||||
view= 1;
|
view= 1;
|
||||||
alias_used= my_strcasecmp(table_alias_charset,
|
|
||||||
tables->table_name, tables->alias);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -3445,6 +3433,10 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
|
|||||||
}
|
}
|
||||||
iterator->set(tables);
|
iterator->set(tables);
|
||||||
|
|
||||||
|
/* for view used tables will be collected in following loop */
|
||||||
|
if (table)
|
||||||
|
thd->used_tables|= table->map;
|
||||||
|
|
||||||
for (; !iterator->end_of_fields(); iterator->next())
|
for (; !iterator->end_of_fields(); iterator->next())
|
||||||
{
|
{
|
||||||
Item *not_used_item;
|
Item *not_used_item;
|
||||||
@ -3457,16 +3449,10 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
|
|||||||
strlen(field_name), ¬_used_item, 0, 0, 0,
|
strlen(field_name), ¬_used_item, 0, 0, 0,
|
||||||
¬_used_field_index, TRUE))
|
¬_used_field_index, TRUE))
|
||||||
{
|
{
|
||||||
Item *item= iterator->item(thd);
|
Item *item= iterator->create_item(thd);
|
||||||
if (view && !thd->lex->current_select->no_wrap_view_item)
|
if (!item)
|
||||||
{
|
goto err;
|
||||||
/*
|
thd->used_tables|= item->used_tables();
|
||||||
as far as we have view, then item point to view_iter, so we
|
|
||||||
can use it directly for this view specific operation
|
|
||||||
*/
|
|
||||||
item= new Item_ref(view_iter.item_ptr(), tables->view_name.str,
|
|
||||||
field_name);
|
|
||||||
}
|
|
||||||
if (!found++)
|
if (!found++)
|
||||||
(void) it->replace(item); // Replace '*'
|
(void) it->replace(item); // Replace '*'
|
||||||
else
|
else
|
||||||
@ -3537,9 +3523,7 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
|
|||||||
my_message(ER_NO_TABLES_USED, ER(ER_NO_TABLES_USED), MYF(0));
|
my_message(ER_NO_TABLES_USED, ER(ER_NO_TABLES_USED), MYF(0));
|
||||||
else
|
else
|
||||||
my_error(ER_BAD_TABLE_ERROR, MYF(0), table_name);
|
my_error(ER_BAD_TABLE_ERROR, MYF(0), table_name);
|
||||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
|
||||||
err:
|
err:
|
||||||
#endif
|
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3550,16 +3534,25 @@ err:
|
|||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
setup_conds()
|
setup_conds()
|
||||||
thd thread handler
|
thd thread handler
|
||||||
tables list of tables for name resolving
|
|
||||||
leaves list of leaves of join table tree
|
leaves list of leaves of join table tree
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds)
|
int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
|
||||||
|
COND **conds)
|
||||||
{
|
{
|
||||||
SELECT_LEX *select_lex= thd->lex->current_select;
|
SELECT_LEX *select_lex= thd->lex->current_select;
|
||||||
Query_arena *arena= thd->current_arena, backup;
|
Query_arena *arena= thd->current_arena, backup;
|
||||||
bool save_wrapper= thd->lex->current_select->no_wrap_view_item;
|
|
||||||
TABLE_LIST *table= NULL; // For HP compilers
|
TABLE_LIST *table= NULL; // For HP compilers
|
||||||
|
/*
|
||||||
|
it_is_update set to TRUE when tables of primary SELECT_LEX (SELECT_LEX
|
||||||
|
which belong to LEX, i.e. most up SELECT) will be updated by
|
||||||
|
INSERT/UPDATE/LOAD
|
||||||
|
NOTE: using this condition helps to prevent call of prepare_check_option()
|
||||||
|
from subquery of VIEW, because tables of subquery belongs to VIEW
|
||||||
|
(see condition before prepare_check_option() call)
|
||||||
|
*/
|
||||||
|
bool it_is_update= (select_lex == &thd->lex->select_lex) &&
|
||||||
|
thd->lex->which_check_option_applicable();
|
||||||
DBUG_ENTER("setup_conds");
|
DBUG_ENTER("setup_conds");
|
||||||
|
|
||||||
if (select_lex->conds_processed_with_permanent_arena ||
|
if (select_lex->conds_processed_with_permanent_arena ||
|
||||||
@ -3568,12 +3561,17 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds)
|
|||||||
|
|
||||||
thd->set_query_id=1;
|
thd->set_query_id=1;
|
||||||
|
|
||||||
thd->lex->current_select->no_wrap_view_item= 0;
|
for (table= tables; table; table= table->next_local)
|
||||||
|
{
|
||||||
|
if (table->prepare_where(thd, conds, FALSE))
|
||||||
|
goto err_no_arena;
|
||||||
|
}
|
||||||
|
|
||||||
select_lex->cond_count= 0;
|
select_lex->cond_count= 0;
|
||||||
if (*conds)
|
if (*conds)
|
||||||
{
|
{
|
||||||
thd->where="where clause";
|
thd->where="where clause";
|
||||||
if (!(*conds)->fixed && (*conds)->fix_fields(thd, tables, conds) ||
|
if (!(*conds)->fixed && (*conds)->fix_fields(thd, conds) ||
|
||||||
(*conds)->check_cols(1))
|
(*conds)->check_cols(1))
|
||||||
goto err_no_arena;
|
goto err_no_arena;
|
||||||
}
|
}
|
||||||
@ -3591,11 +3589,12 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds)
|
|||||||
/* Make a join an a expression */
|
/* Make a join an a expression */
|
||||||
thd->where="on clause";
|
thd->where="on clause";
|
||||||
if (!embedded->on_expr->fixed &&
|
if (!embedded->on_expr->fixed &&
|
||||||
embedded->on_expr->fix_fields(thd, tables, &embedded->on_expr) ||
|
embedded->on_expr->fix_fields(thd, &embedded->on_expr) ||
|
||||||
embedded->on_expr->check_cols(1))
|
embedded->on_expr->check_cols(1))
|
||||||
goto err_no_arena;
|
goto err_no_arena;
|
||||||
select_lex->cond_count++;
|
select_lex->cond_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (embedded->natural_join)
|
if (embedded->natural_join)
|
||||||
{
|
{
|
||||||
/* Make a join of all fields wich have the same name */
|
/* Make a join of all fields wich have the same name */
|
||||||
@ -3675,7 +3674,8 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds)
|
|||||||
{
|
{
|
||||||
if (t2_field != view_ref_found)
|
if (t2_field != view_ref_found)
|
||||||
{
|
{
|
||||||
if (!(item_t2= new Item_field(thd, t2_field)))
|
if (!(item_t2= new Item_field(thd, &select_lex->context,
|
||||||
|
t2_field)))
|
||||||
goto err;
|
goto err;
|
||||||
/* Mark field used for table cache */
|
/* Mark field used for table cache */
|
||||||
t2_field->query_id= thd->query_id;
|
t2_field->query_id= thd->query_id;
|
||||||
@ -3687,7 +3687,7 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds)
|
|||||||
t1_field->query_id= thd->query_id;
|
t1_field->query_id= thd->query_id;
|
||||||
t1->used_keys.intersect(t1_field->part_of_key);
|
t1->used_keys.intersect(t1_field->part_of_key);
|
||||||
}
|
}
|
||||||
Item_func_eq *tmp= new Item_func_eq(iterator->item(thd),
|
Item_func_eq *tmp= new Item_func_eq(iterator->create_item(thd),
|
||||||
item_t2);
|
item_t2);
|
||||||
if (!tmp)
|
if (!tmp)
|
||||||
goto err;
|
goto err;
|
||||||
@ -3703,7 +3703,7 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds)
|
|||||||
{
|
{
|
||||||
COND *on_expr= cond_and;
|
COND *on_expr= cond_and;
|
||||||
if (!on_expr->fixed)
|
if (!on_expr->fixed)
|
||||||
on_expr->fix_fields(thd, 0, &on_expr);
|
on_expr->fix_fields(thd, &on_expr);
|
||||||
if (!embedded->outer_join) // Not left join
|
if (!embedded->outer_join) // Not left join
|
||||||
{
|
{
|
||||||
*conds= and_conds(*conds, cond_and);
|
*conds= and_conds(*conds, cond_and);
|
||||||
@ -3712,7 +3712,7 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds)
|
|||||||
thd->restore_backup_item_arena(arena, &backup);
|
thd->restore_backup_item_arena(arena, &backup);
|
||||||
if (*conds && !(*conds)->fixed)
|
if (*conds && !(*conds)->fixed)
|
||||||
{
|
{
|
||||||
if ((*conds)->fix_fields(thd, tables, conds))
|
if ((*conds)->fix_fields(thd, conds))
|
||||||
goto err_no_arena;
|
goto err_no_arena;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3724,8 +3724,7 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds)
|
|||||||
thd->restore_backup_item_arena(arena, &backup);
|
thd->restore_backup_item_arena(arena, &backup);
|
||||||
if (embedded->on_expr && !embedded->on_expr->fixed)
|
if (embedded->on_expr && !embedded->on_expr->fixed)
|
||||||
{
|
{
|
||||||
if (embedded->on_expr->fix_fields(thd, tables,
|
if (embedded->on_expr->fix_fields(thd, &embedded->on_expr))
|
||||||
&embedded->on_expr))
|
|
||||||
goto err_no_arena;
|
goto err_no_arena;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3737,6 +3736,20 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds)
|
|||||||
}
|
}
|
||||||
while (embedding &&
|
while (embedding &&
|
||||||
embedding->nested_join->join_list.head() == embedded);
|
embedding->nested_join->join_list.head() == embedded);
|
||||||
|
|
||||||
|
/* process CHECK OPTION */
|
||||||
|
if (it_is_update)
|
||||||
|
{
|
||||||
|
TABLE_LIST *view= table->belong_to_view;
|
||||||
|
if (!view)
|
||||||
|
view= table;
|
||||||
|
if (view->effective_with_check)
|
||||||
|
{
|
||||||
|
if (view->prepare_check_option(thd))
|
||||||
|
goto err_no_arena;
|
||||||
|
thd->change_item_tree(&table->check_option, view->check_option);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!thd->current_arena->is_conventional())
|
if (!thd->current_arena->is_conventional())
|
||||||
@ -3750,14 +3763,12 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds)
|
|||||||
select_lex->where= *conds;
|
select_lex->where= *conds;
|
||||||
select_lex->conds_processed_with_permanent_arena= 1;
|
select_lex->conds_processed_with_permanent_arena= 1;
|
||||||
}
|
}
|
||||||
thd->lex->current_select->no_wrap_view_item= save_wrapper;
|
|
||||||
DBUG_RETURN(test(thd->net.report_error));
|
DBUG_RETURN(test(thd->net.report_error));
|
||||||
|
|
||||||
err:
|
err:
|
||||||
if (arena)
|
if (arena)
|
||||||
thd->restore_backup_item_arena(arena, &backup);
|
thd->restore_backup_item_arena(arena, &backup);
|
||||||
err_no_arena:
|
err_no_arena:
|
||||||
thd->lex->current_select->no_wrap_view_item= save_wrapper;
|
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1451,17 +1451,16 @@ int select_dumpvar::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
|
|||||||
(void)local_vars.push_back(new Item_splocal(mv->s, mv->offset));
|
(void)local_vars.push_back(new Item_splocal(mv->s, mv->offset));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Item_func_set_user_var *xx = new Item_func_set_user_var(mv->s, item);
|
Item_func_set_user_var *var= new Item_func_set_user_var(mv->s, item);
|
||||||
/*
|
/*
|
||||||
Item_func_set_user_var can't substitute something else on its place =>
|
Item_func_set_user_var can't substitute something else on its place =>
|
||||||
0 can be passed as last argument (reference on item)
|
0 can be passed as last argument (reference on item)
|
||||||
Item_func_set_user_var can't be fixed after creation, so we do not
|
Item_func_set_user_var can't be fixed after creation, so we do not
|
||||||
check xx->fixed
|
check var->fixed
|
||||||
*/
|
*/
|
||||||
xx->fix_fields(thd, (TABLE_LIST*) thd->lex->select_lex.table_list.first,
|
var->fix_fields(thd, 0);
|
||||||
0);
|
var->fix_length_and_dec();
|
||||||
xx->fix_length_and_dec();
|
vars.push_back(var);
|
||||||
vars.push_back(xx);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -1538,15 +1537,19 @@ void Statement::set_statement(Statement *stmt)
|
|||||||
void
|
void
|
||||||
Statement::set_n_backup_statement(Statement *stmt, Statement *backup)
|
Statement::set_n_backup_statement(Statement *stmt, Statement *backup)
|
||||||
{
|
{
|
||||||
|
DBUG_ENTER("Statement::set_n_backup_statement");
|
||||||
backup->set_statement(this);
|
backup->set_statement(this);
|
||||||
set_statement(stmt);
|
set_statement(stmt);
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Statement::restore_backup_statement(Statement *stmt, Statement *backup)
|
void Statement::restore_backup_statement(Statement *stmt, Statement *backup)
|
||||||
{
|
{
|
||||||
|
DBUG_ENTER("Statement::restore_backup_statement");
|
||||||
stmt->set_statement(this);
|
stmt->set_statement(this);
|
||||||
set_statement(backup);
|
set_statement(backup);
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1569,6 +1572,7 @@ void Query_arena::set_n_backup_item_arena(Query_arena *set, Query_arena *backup)
|
|||||||
{
|
{
|
||||||
DBUG_ENTER("Query_arena::set_n_backup_item_arena");
|
DBUG_ENTER("Query_arena::set_n_backup_item_arena");
|
||||||
DBUG_ASSERT(backup->is_backup_arena == FALSE);
|
DBUG_ASSERT(backup->is_backup_arena == FALSE);
|
||||||
|
|
||||||
backup->set_item_arena(this);
|
backup->set_item_arena(this);
|
||||||
set_item_arena(set);
|
set_item_arena(set);
|
||||||
#ifndef DBUG_OFF
|
#ifndef DBUG_OFF
|
||||||
|
@ -300,7 +300,9 @@ bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds)
|
|||||||
SELECT_LEX *select_lex= &thd->lex->select_lex;
|
SELECT_LEX *select_lex= &thd->lex->select_lex;
|
||||||
DBUG_ENTER("mysql_prepare_delete");
|
DBUG_ENTER("mysql_prepare_delete");
|
||||||
|
|
||||||
if (setup_tables(thd, table_list, conds, &select_lex->leaf_tables, FALSE) ||
|
if (setup_tables(thd, &thd->lex->select_lex.context,
|
||||||
|
table_list, conds, &select_lex->leaf_tables,
|
||||||
|
FALSE) ||
|
||||||
setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
|
setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
|
||||||
setup_ftfuncs(select_lex))
|
setup_ftfuncs(select_lex))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
@ -356,7 +358,8 @@ bool mysql_multi_delete_prepare(THD *thd)
|
|||||||
|
|
||||||
lex->query_tables also point on local list of DELETE SELECT_LEX
|
lex->query_tables also point on local list of DELETE SELECT_LEX
|
||||||
*/
|
*/
|
||||||
if (setup_tables(thd, lex->query_tables, &lex->select_lex.where,
|
if (setup_tables(thd, &thd->lex->select_lex.context,
|
||||||
|
lex->query_tables, &lex->select_lex.where,
|
||||||
&lex->select_lex.leaf_tables, FALSE))
|
&lex->select_lex.leaf_tables, FALSE))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
|
@ -114,6 +114,10 @@ int mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *orig_table_list)
|
|||||||
bool is_union= first_select->next_select() &&
|
bool is_union= first_select->next_select() &&
|
||||||
first_select->next_select()->linkage == UNION_TYPE;
|
first_select->next_select()->linkage == UNION_TYPE;
|
||||||
|
|
||||||
|
/* prevent name resolving out of derived table */
|
||||||
|
for (SELECT_LEX *sl= first_select; sl; sl= sl->next_select())
|
||||||
|
sl->context.outer_context= 0;
|
||||||
|
|
||||||
if (!(derived_result= new select_union(0)))
|
if (!(derived_result= new select_union(0)))
|
||||||
DBUG_RETURN(1); // out of memory
|
DBUG_RETURN(1); // out of memory
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ bool mysql_do(THD *thd, List<Item> &values)
|
|||||||
List_iterator<Item> li(values);
|
List_iterator<Item> li(values);
|
||||||
Item *value;
|
Item *value;
|
||||||
DBUG_ENTER("mysql_do");
|
DBUG_ENTER("mysql_do");
|
||||||
if (setup_fields(thd, 0, 0, values, 0, 0, 0))
|
if (setup_fields(thd, 0, values, 0, 0, 0))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
while ((value = li++))
|
while ((value = li++))
|
||||||
value->val_int();
|
value->val_int();
|
||||||
|
@ -353,7 +353,9 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
|
|||||||
LINT_INIT(key);
|
LINT_INIT(key);
|
||||||
LINT_INIT(key_len);
|
LINT_INIT(key_len);
|
||||||
|
|
||||||
list.push_front(new Item_field(NULL,NULL,"*"));
|
thd->lex->select_lex.context.resolve_in_table_list_only(tables);
|
||||||
|
list.push_front(new Item_field(&thd->lex->select_lex.context,
|
||||||
|
NULL, NULL, "*"));
|
||||||
List_iterator<Item> it(list);
|
List_iterator<Item> it(list);
|
||||||
it++;
|
it++;
|
||||||
|
|
||||||
@ -410,7 +412,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
|
|||||||
tables->table=table;
|
tables->table=table;
|
||||||
|
|
||||||
if (cond && ((!cond->fixed &&
|
if (cond && ((!cond->fixed &&
|
||||||
cond->fix_fields(thd, tables, &cond)) || cond->check_cols(1)))
|
cond->fix_fields(thd, &cond)) || cond->check_cols(1)))
|
||||||
goto err0;
|
goto err0;
|
||||||
|
|
||||||
if (keyname)
|
if (keyname)
|
||||||
@ -422,7 +424,8 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (insert_fields(thd, tables, tables->db, tables->alias, &it, 0))
|
if (insert_fields(thd, &thd->lex->select_lex.context,
|
||||||
|
tables->db, tables->alias, &it, 0))
|
||||||
goto err0;
|
goto err0;
|
||||||
|
|
||||||
protocol->send_fields(&list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF);
|
protocol->send_fields(&list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF);
|
||||||
@ -505,7 +508,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
|
|||||||
{
|
{
|
||||||
// 'item' can be changed by fix_fields() call
|
// 'item' can be changed by fix_fields() call
|
||||||
if ((!item->fixed &&
|
if ((!item->fixed &&
|
||||||
item->fix_fields(thd, tables, it_ke.ref())) ||
|
item->fix_fields(thd, it_ke.ref())) ||
|
||||||
(item= *it_ke.ref())->check_cols(1))
|
(item= *it_ke.ref())->check_cols(1))
|
||||||
goto err;
|
goto err;
|
||||||
if (item->used_tables() & ~RAND_TABLE_BIT)
|
if (item->used_tables() & ~RAND_TABLE_BIT)
|
||||||
|
@ -81,11 +81,14 @@ enum enum_used_fields
|
|||||||
static bool init_fields(THD *thd, TABLE_LIST *tables,
|
static bool init_fields(THD *thd, TABLE_LIST *tables,
|
||||||
struct st_find_field *find_fields, uint count)
|
struct st_find_field *find_fields, uint count)
|
||||||
{
|
{
|
||||||
|
Name_resolution_context *context= &thd->lex->select_lex.context;
|
||||||
DBUG_ENTER("init_fields");
|
DBUG_ENTER("init_fields");
|
||||||
|
context->resolve_in_table_list_only(tables);
|
||||||
for (; count-- ; find_fields++)
|
for (; count-- ; find_fields++)
|
||||||
{
|
{
|
||||||
/* We have to use 'new' here as field will be re_linked on free */
|
/* We have to use 'new' here as field will be re_linked on free */
|
||||||
Item_field *field= new Item_field("mysql", find_fields->table_name,
|
Item_field *field= new Item_field(context,
|
||||||
|
"mysql", find_fields->table_name,
|
||||||
find_fields->field_name);
|
find_fields->field_name);
|
||||||
if (!(find_fields->field= find_field_in_tables(thd, field, tables,
|
if (!(find_fields->field= find_field_in_tables(thd, field, tables,
|
||||||
0, REPORT_ALL_ERRORS, 1)))
|
0, REPORT_ALL_ERRORS, 1)))
|
||||||
@ -544,7 +547,6 @@ int send_variant_2_list(MEM_ROOT *mem_root, Protocol *protocol,
|
|||||||
prepare_simple_select()
|
prepare_simple_select()
|
||||||
thd Thread handler
|
thd Thread handler
|
||||||
cond WHERE part of select
|
cond WHERE part of select
|
||||||
tables list of tables, used in WHERE
|
|
||||||
table goal table
|
table goal table
|
||||||
|
|
||||||
error code of error (out)
|
error code of error (out)
|
||||||
@ -553,11 +555,11 @@ int send_variant_2_list(MEM_ROOT *mem_root, Protocol *protocol,
|
|||||||
# created SQL_SELECT
|
# created SQL_SELECT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SQL_SELECT *prepare_simple_select(THD *thd, Item *cond, TABLE_LIST *tables,
|
SQL_SELECT *prepare_simple_select(THD *thd, Item *cond,
|
||||||
TABLE *table, int *error)
|
TABLE *table, int *error)
|
||||||
{
|
{
|
||||||
if (!cond->fixed)
|
if (!cond->fixed)
|
||||||
cond->fix_fields(thd, tables, &cond); // can never fail
|
cond->fix_fields(thd, &cond); // can never fail
|
||||||
|
|
||||||
/* Assume that no indexes cover all required fields */
|
/* Assume that no indexes cover all required fields */
|
||||||
table->used_keys.clear_all();
|
table->used_keys.clear_all();
|
||||||
@ -599,7 +601,7 @@ SQL_SELECT *prepare_select_for_name(THD *thd, const char *mask, uint mlen,
|
|||||||
new Item_string("\\",1,&my_charset_latin1));
|
new Item_string("\\",1,&my_charset_latin1));
|
||||||
if (thd->is_fatal_error)
|
if (thd->is_fatal_error)
|
||||||
return 0; // OOM
|
return 0; // OOM
|
||||||
return prepare_simple_select(thd,cond,tables,table,error);
|
return prepare_simple_select(thd, cond, table, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -651,7 +653,8 @@ bool mysqld_help(THD *thd, const char *mask)
|
|||||||
|
|
||||||
tables do not contain VIEWs => we can pass 0 as conds
|
tables do not contain VIEWs => we can pass 0 as conds
|
||||||
*/
|
*/
|
||||||
setup_tables(thd, tables, 0, &leaves, FALSE);
|
setup_tables(thd, &thd->lex->select_lex.context,
|
||||||
|
tables, 0, &leaves, FALSE);
|
||||||
memcpy((char*) used_fields, (char*) init_used_fields, sizeof(used_fields));
|
memcpy((char*) used_fields, (char*) init_used_fields, sizeof(used_fields));
|
||||||
if (init_fields(thd, tables, used_fields, array_elements(used_fields)))
|
if (init_fields(thd, tables, used_fields, array_elements(used_fields)))
|
||||||
goto error;
|
goto error;
|
||||||
@ -719,13 +722,13 @@ bool mysqld_help(THD *thd, const char *mask)
|
|||||||
new Item_func_equal(new Item_field(cat_cat_id),
|
new Item_func_equal(new Item_field(cat_cat_id),
|
||||||
new Item_int((int32)category_id));
|
new Item_int((int32)category_id));
|
||||||
if (!(select= prepare_simple_select(thd, cond_topic_by_cat,
|
if (!(select= prepare_simple_select(thd, cond_topic_by_cat,
|
||||||
tables,tables[0].table,&error)))
|
tables[0].table, &error)))
|
||||||
goto error;
|
goto error;
|
||||||
get_all_items_for_category(thd,tables[0].table,
|
get_all_items_for_category(thd,tables[0].table,
|
||||||
used_fields[help_topic_name].field,
|
used_fields[help_topic_name].field,
|
||||||
select,&topics_list);
|
select,&topics_list);
|
||||||
delete select;
|
delete select;
|
||||||
if (!(select= prepare_simple_select(thd,cond_cat_by_cat,tables,
|
if (!(select= prepare_simple_select(thd, cond_cat_by_cat,
|
||||||
tables[1].table, &error)))
|
tables[1].table, &error)))
|
||||||
goto error;
|
goto error;
|
||||||
get_all_items_for_category(thd,tables[1].table,
|
get_all_items_for_category(thd,tables[1].table,
|
||||||
|
@ -31,7 +31,7 @@ static void end_delayed_insert(THD *thd);
|
|||||||
extern "C" pthread_handler_decl(handle_delayed_insert,arg);
|
extern "C" pthread_handler_decl(handle_delayed_insert,arg);
|
||||||
static void unlink_blobs(register TABLE *table);
|
static void unlink_blobs(register TABLE *table);
|
||||||
#endif
|
#endif
|
||||||
static bool check_view_insertability(TABLE_LIST *view, query_id_t query_id);
|
static bool check_view_insertability(THD *thd, TABLE_LIST *view);
|
||||||
|
|
||||||
/* Define to force use of my_malloc() if the allocated memory block is big */
|
/* Define to force use of my_malloc() if the allocated memory block is big */
|
||||||
|
|
||||||
@ -106,7 +106,11 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // Part field list
|
{ // Part field list
|
||||||
TABLE_LIST *save_next;
|
Name_resolution_context *context= &thd->lex->select_lex.context;
|
||||||
|
TABLE_LIST *save_next= table_list->next_local,
|
||||||
|
*save_context= context->table_list;
|
||||||
|
bool save_resolve_in_select_list=
|
||||||
|
thd->lex->select_lex.context.resolve_in_select_list;
|
||||||
int res;
|
int res;
|
||||||
if (fields.elements != values.elements)
|
if (fields.elements != values.elements)
|
||||||
{
|
{
|
||||||
@ -115,12 +119,15 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
|
|||||||
}
|
}
|
||||||
|
|
||||||
thd->dupp_field=0;
|
thd->dupp_field=0;
|
||||||
thd->lex->select_lex.no_wrap_view_item= 1;
|
thd->lex->select_lex.no_wrap_view_item= TRUE;
|
||||||
save_next= table_list->next_local; // fields only from first table
|
/* fields only from first table */
|
||||||
table_list->next_local= 0;
|
table_list->next_local= 0;
|
||||||
res= setup_fields(thd, 0, table_list, fields, 1, 0, 0);
|
context->resolve_in_table_list_only(table_list);
|
||||||
|
res= setup_fields(thd, 0, fields, 1, 0, 0);
|
||||||
table_list->next_local= save_next;
|
table_list->next_local= save_next;
|
||||||
thd->lex->select_lex.no_wrap_view_item= 0;
|
thd->lex->select_lex.no_wrap_view_item= FALSE;
|
||||||
|
context->table_list= save_context;
|
||||||
|
context->resolve_in_select_list= save_resolve_in_select_list;
|
||||||
if (res)
|
if (res)
|
||||||
return -1;
|
return -1;
|
||||||
if (table_list->effective_algorithm == VIEW_ALGORITHM_MERGE)
|
if (table_list->effective_algorithm == VIEW_ALGORITHM_MERGE)
|
||||||
@ -159,7 +166,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
|
|||||||
|
|
||||||
if (check_key_in_view(thd, table_list) ||
|
if (check_key_in_view(thd, table_list) ||
|
||||||
(table_list->view &&
|
(table_list->view &&
|
||||||
check_view_insertability(table_list, thd->query_id)))
|
check_view_insertability(thd, table_list)))
|
||||||
{
|
{
|
||||||
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "INSERT");
|
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "INSERT");
|
||||||
return -1;
|
return -1;
|
||||||
@ -209,7 +216,7 @@ static int check_update_fields(THD *thd, TABLE_LIST *insert_table_list,
|
|||||||
Check the fields we are going to modify. This will set the query_id
|
Check the fields we are going to modify. This will set the query_id
|
||||||
of all used fields to the threads query_id.
|
of all used fields to the threads query_id.
|
||||||
*/
|
*/
|
||||||
if (setup_fields(thd, 0, insert_table_list, update_fields, 1, 0, 0))
|
if (setup_fields(thd, 0, update_fields, 1, 0, 0))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (table->timestamp_field)
|
if (table->timestamp_field)
|
||||||
@ -247,6 +254,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
|||||||
ulonglong id;
|
ulonglong id;
|
||||||
COPY_INFO info;
|
COPY_INFO info;
|
||||||
TABLE *table= 0;
|
TABLE *table= 0;
|
||||||
|
TABLE_LIST *next_local;
|
||||||
List_iterator_fast<List_item> its(values_list);
|
List_iterator_fast<List_item> its(values_list);
|
||||||
List_item *values;
|
List_item *values;
|
||||||
#ifndef EMBEDDED_LIBRARY
|
#ifndef EMBEDDED_LIBRARY
|
||||||
@ -327,7 +335,9 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
|||||||
/* mysql_prepare_insert set table_list->table if it was not set */
|
/* mysql_prepare_insert set table_list->table if it was not set */
|
||||||
table= table_list->table;
|
table= table_list->table;
|
||||||
|
|
||||||
// is table which we are changing used somewhere in other parts of query
|
next_local= table_list->next_local;
|
||||||
|
table_list->next_local= 0;
|
||||||
|
thd->lex->select_lex.context.resolve_in_table_list_only(table_list);
|
||||||
value_count= values->elements;
|
value_count= values->elements;
|
||||||
while ((values= its++))
|
while ((values= its++))
|
||||||
{
|
{
|
||||||
@ -337,10 +347,11 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
|||||||
my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), counter);
|
my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), counter);
|
||||||
goto abort;
|
goto abort;
|
||||||
}
|
}
|
||||||
if (setup_fields(thd, 0, table_list, *values, 0, 0, 0))
|
if (setup_fields(thd, 0, *values, 0, 0, 0))
|
||||||
goto abort;
|
goto abort;
|
||||||
}
|
}
|
||||||
its.rewind ();
|
its.rewind ();
|
||||||
|
table_list->next_local= next_local;
|
||||||
/*
|
/*
|
||||||
Fill in the given fields and dump it to the table file
|
Fill in the given fields and dump it to the table file
|
||||||
*/
|
*/
|
||||||
@ -387,12 +398,16 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
|||||||
MODE_STRICT_ALL_TABLES)));
|
MODE_STRICT_ALL_TABLES)));
|
||||||
|
|
||||||
if ((fields.elements || !value_count) &&
|
if ((fields.elements || !value_count) &&
|
||||||
check_that_all_fields_are_given_values(thd, table))
|
check_that_all_fields_are_given_values(thd, table, table_list))
|
||||||
{
|
{
|
||||||
/* thd->net.report_error is now set, which will abort the next loop */
|
/* thd->net.report_error is now set, which will abort the next loop */
|
||||||
error= 1;
|
error= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (table_list->prepare_where(thd, 0, TRUE) ||
|
||||||
|
table_list->prepare_check_option(thd))
|
||||||
|
error= 1;
|
||||||
|
|
||||||
while ((values= its++))
|
while ((values= its++))
|
||||||
{
|
{
|
||||||
if (fields.elements || !value_count)
|
if (fields.elements || !value_count)
|
||||||
@ -596,6 +611,7 @@ abort:
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
check_view_insertability()
|
check_view_insertability()
|
||||||
|
thd - thread handler
|
||||||
view - reference on VIEW
|
view - reference on VIEW
|
||||||
|
|
||||||
IMPLEMENTATION
|
IMPLEMENTATION
|
||||||
@ -612,7 +628,7 @@ abort:
|
|||||||
TRUE - can't be used for insert
|
TRUE - can't be used for insert
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static bool check_view_insertability(TABLE_LIST *view, query_id_t query_id)
|
static bool check_view_insertability(THD * thd, TABLE_LIST *view)
|
||||||
{
|
{
|
||||||
uint num= view->view->select_lex.item_list.elements;
|
uint num= view->view->select_lex.item_list.elements;
|
||||||
TABLE *table= view->table;
|
TABLE *table= view->table;
|
||||||
@ -620,15 +636,25 @@ static bool check_view_insertability(TABLE_LIST *view, query_id_t query_id)
|
|||||||
*trans_end= trans_start + num;
|
*trans_end= trans_start + num;
|
||||||
Field_translator *trans;
|
Field_translator *trans;
|
||||||
Field **field_ptr= table->field;
|
Field **field_ptr= table->field;
|
||||||
query_id_t other_query_id= query_id - 1;
|
uint used_fields_buff_size= (table->s->fields + 7) / 8;
|
||||||
|
uchar *used_fields_buff= (uchar*)thd->alloc(used_fields_buff_size);
|
||||||
|
MY_BITMAP used_fields;
|
||||||
DBUG_ENTER("check_key_in_view");
|
DBUG_ENTER("check_key_in_view");
|
||||||
|
|
||||||
|
if (!used_fields_buff)
|
||||||
|
DBUG_RETURN(TRUE); // EOM
|
||||||
|
|
||||||
DBUG_ASSERT(view->table != 0 && view->field_translation != 0);
|
DBUG_ASSERT(view->table != 0 && view->field_translation != 0);
|
||||||
|
|
||||||
|
bitmap_init(&used_fields, used_fields_buff, used_fields_buff_size * 8, 0);
|
||||||
|
bitmap_clear_all(&used_fields);
|
||||||
|
|
||||||
view->contain_auto_increment= 0;
|
view->contain_auto_increment= 0;
|
||||||
/* check simplicity and prepare unique test of view */
|
/* check simplicity and prepare unique test of view */
|
||||||
for (trans= trans_start; trans != trans_end; trans++)
|
for (trans= trans_start; trans != trans_end; trans++)
|
||||||
{
|
{
|
||||||
|
if (!trans->item->fixed && trans->item->fix_fields(thd, &trans->item))
|
||||||
|
return TRUE;
|
||||||
Item_field *field;
|
Item_field *field;
|
||||||
/* simple SELECT list entry (field without expression) */
|
/* simple SELECT list entry (field without expression) */
|
||||||
if (!(field= trans->item->filed_for_view_update()))
|
if (!(field= trans->item->filed_for_view_update()))
|
||||||
@ -636,7 +662,6 @@ static bool check_view_insertability(TABLE_LIST *view, query_id_t query_id)
|
|||||||
if (field->field->unireg_check == Field::NEXT_NUMBER)
|
if (field->field->unireg_check == Field::NEXT_NUMBER)
|
||||||
view->contain_auto_increment= 1;
|
view->contain_auto_increment= 1;
|
||||||
/* prepare unique test */
|
/* prepare unique test */
|
||||||
field->field->query_id= other_query_id;
|
|
||||||
/*
|
/*
|
||||||
remove collation (or other transparent for update function) if we have
|
remove collation (or other transparent for update function) if we have
|
||||||
it
|
it
|
||||||
@ -648,29 +673,12 @@ static bool check_view_insertability(TABLE_LIST *view, query_id_t query_id)
|
|||||||
{
|
{
|
||||||
/* Thanks to test above, we know that all columns are of type Item_field */
|
/* Thanks to test above, we know that all columns are of type Item_field */
|
||||||
Item_field *field= (Item_field *)trans->item;
|
Item_field *field= (Item_field *)trans->item;
|
||||||
if (field->field->query_id == query_id)
|
/* check fields belong to table in which we are inserting */
|
||||||
|
if (field->field->table == table &&
|
||||||
|
bitmap_fast_test_and_set(&used_fields, field->field->field_index))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
field->field->query_id= query_id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* VIEW contain all fields without default value */
|
|
||||||
for (; *field_ptr; field_ptr++)
|
|
||||||
{
|
|
||||||
Field *field= *field_ptr;
|
|
||||||
/* field have not default value */
|
|
||||||
if ((field->type() == FIELD_TYPE_BLOB) &&
|
|
||||||
(table->timestamp_field != field ||
|
|
||||||
field->unireg_check == Field::TIMESTAMP_UN_FIELD))
|
|
||||||
{
|
|
||||||
for (trans= trans_start; ; trans++)
|
|
||||||
{
|
|
||||||
if (trans == trans_end)
|
|
||||||
DBUG_RETURN(TRUE); // Field was not part of view
|
|
||||||
if (((Item_field *)trans->item)->field == *field_ptr)
|
|
||||||
break; // ok
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -698,7 +706,8 @@ static bool mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list,
|
|||||||
bool insert_into_view= (table_list->view != 0);
|
bool insert_into_view= (table_list->view != 0);
|
||||||
DBUG_ENTER("mysql_prepare_insert_check_table");
|
DBUG_ENTER("mysql_prepare_insert_check_table");
|
||||||
|
|
||||||
if (setup_tables(thd, table_list, where, &thd->lex->select_lex.leaf_tables,
|
if (setup_tables(thd, &thd->lex->select_lex.context,
|
||||||
|
table_list, where, &thd->lex->select_lex.leaf_tables,
|
||||||
select_insert))
|
select_insert))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
@ -711,7 +720,7 @@ static bool mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list,
|
|||||||
table_list->view_db.str, table_list->view_name.str);
|
table_list->view_db.str, table_list->view_name.str);
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
}
|
}
|
||||||
DBUG_RETURN(insert_view_fields(&fields, table_list));
|
DBUG_RETURN(insert_view_fields(thd, &fields, table_list));
|
||||||
}
|
}
|
||||||
|
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
@ -741,8 +750,10 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table,
|
|||||||
enum_duplicates duplic,
|
enum_duplicates duplic,
|
||||||
COND **where, bool select_insert)
|
COND **where, bool select_insert)
|
||||||
{
|
{
|
||||||
|
TABLE_LIST *save_table_list= thd->lex->select_lex.context.table_list;
|
||||||
bool insert_into_view= (table_list->view != 0);
|
bool insert_into_view= (table_list->view != 0);
|
||||||
/* TODO: use this condition for 'WITH CHECK OPTION' */
|
bool save_resolve_in_select_list=
|
||||||
|
thd->lex->select_lex.context.resolve_in_select_list;
|
||||||
bool res;
|
bool res;
|
||||||
TABLE_LIST *next_local;
|
TABLE_LIST *next_local;
|
||||||
DBUG_ENTER("mysql_prepare_insert");
|
DBUG_ENTER("mysql_prepare_insert");
|
||||||
@ -750,6 +761,26 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table,
|
|||||||
(ulong)table_list, (ulong)table,
|
(ulong)table_list, (ulong)table,
|
||||||
(int)insert_into_view));
|
(int)insert_into_view));
|
||||||
|
|
||||||
|
/*
|
||||||
|
For subqueries in VALUES() we should not see the table in which we are
|
||||||
|
inserting (for INSERT ... SELECT this is done by changing table_list,
|
||||||
|
because INSERT ... SELECT share SELECT_LEX it with SELECT.
|
||||||
|
*/
|
||||||
|
if (!select_insert)
|
||||||
|
{
|
||||||
|
for (SELECT_LEX_UNIT *un= thd->lex->select_lex.first_inner_unit();
|
||||||
|
un;
|
||||||
|
un= un->next_unit())
|
||||||
|
{
|
||||||
|
for (SELECT_LEX *sl= un->first_select();
|
||||||
|
sl;
|
||||||
|
sl= sl->next_select())
|
||||||
|
{
|
||||||
|
sl->context.outer_context= 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (duplic == DUP_UPDATE)
|
if (duplic == DUP_UPDATE)
|
||||||
{
|
{
|
||||||
/* it should be allocated before Item::fix_fields() */
|
/* it should be allocated before Item::fix_fields() */
|
||||||
@ -763,29 +794,37 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table,
|
|||||||
|
|
||||||
next_local= table_list->next_local;
|
next_local= table_list->next_local;
|
||||||
table_list->next_local= 0;
|
table_list->next_local= 0;
|
||||||
|
thd->lex->select_lex.context.resolve_in_table_list_only(table_list);
|
||||||
if ((values && check_insert_fields(thd, table_list, fields, *values,
|
if ((values && check_insert_fields(thd, table_list, fields, *values,
|
||||||
!insert_into_view)) ||
|
!insert_into_view)) ||
|
||||||
(values && setup_fields(thd, 0, table_list, *values, 0, 0, 0)) ||
|
(values && setup_fields(thd, 0, *values, 0, 0, 0)) ||
|
||||||
(duplic == DUP_UPDATE &&
|
(duplic == DUP_UPDATE &&
|
||||||
((thd->lex->select_lex.no_wrap_view_item= 1,
|
((thd->lex->select_lex.no_wrap_view_item= TRUE,
|
||||||
(res= check_update_fields(thd, table_list, update_fields)),
|
(res= check_update_fields(thd, table_list, update_fields)),
|
||||||
thd->lex->select_lex.no_wrap_view_item= 0,
|
thd->lex->select_lex.no_wrap_view_item= FALSE,
|
||||||
res) ||
|
res) ||
|
||||||
setup_fields(thd, 0, table_list, update_values, 1, 0, 0))))
|
setup_fields(thd, 0, update_values, 1, 0, 0))))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
table_list->next_local= next_local;
|
table_list->next_local= next_local;
|
||||||
|
thd->lex->select_lex.context.table_list= save_table_list;
|
||||||
|
thd->lex->select_lex.context.resolve_in_select_list=
|
||||||
|
save_resolve_in_select_list;
|
||||||
if (!table)
|
if (!table)
|
||||||
table= table_list->table;
|
table= table_list->table;
|
||||||
|
|
||||||
if (!select_insert && unique_table(table_list, table_list->next_global))
|
if (!select_insert)
|
||||||
|
{
|
||||||
|
Item *fake_conds= 0;
|
||||||
|
if (unique_table(table_list, table_list->next_global))
|
||||||
{
|
{
|
||||||
my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->table_name);
|
my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->table_name);
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
}
|
}
|
||||||
|
thd->lex->select_lex.fix_prepare_information(thd, &fake_conds);
|
||||||
|
thd->lex->select_lex.first_execution= 0;
|
||||||
|
}
|
||||||
if (duplic == DUP_UPDATE || duplic == DUP_REPLACE)
|
if (duplic == DUP_UPDATE || duplic == DUP_REPLACE)
|
||||||
table->file->extra(HA_EXTRA_RETRIEVE_PRIMARY_KEY);
|
table->file->extra(HA_EXTRA_RETRIEVE_PRIMARY_KEY);
|
||||||
thd->lex->select_lex.first_execution= 0;
|
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1038,7 +1077,8 @@ before_trg_err:
|
|||||||
Check that all fields with arn't null_fields are used
|
Check that all fields with arn't null_fields are used
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
int check_that_all_fields_are_given_values(THD *thd, TABLE *entry)
|
int check_that_all_fields_are_given_values(THD *thd, TABLE *entry,
|
||||||
|
TABLE_LIST *table_list)
|
||||||
{
|
{
|
||||||
int err= 0;
|
int err= 0;
|
||||||
for (Field **field=entry->field ; *field ; field++)
|
for (Field **field=entry->field ; *field ; field++)
|
||||||
@ -1046,11 +1086,30 @@ int check_that_all_fields_are_given_values(THD *thd, TABLE *entry)
|
|||||||
if ((*field)->query_id != thd->query_id &&
|
if ((*field)->query_id != thd->query_id &&
|
||||||
((*field)->flags & NO_DEFAULT_VALUE_FLAG) &&
|
((*field)->flags & NO_DEFAULT_VALUE_FLAG) &&
|
||||||
((*field)->real_type() != FIELD_TYPE_ENUM))
|
((*field)->real_type() != FIELD_TYPE_ENUM))
|
||||||
|
{
|
||||||
|
bool view= FALSE;
|
||||||
|
if (table_list)
|
||||||
|
{
|
||||||
|
table_list= (table_list->belong_to_view ?
|
||||||
|
table_list->belong_to_view :
|
||||||
|
table_list);
|
||||||
|
view= (table_list->view);
|
||||||
|
}
|
||||||
|
if (view)
|
||||||
|
{
|
||||||
|
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||||
|
ER_NO_DEFAULT_FOR_VIEW_FIELD,
|
||||||
|
ER(ER_NO_DEFAULT_FOR_VIEW_FIELD),
|
||||||
|
table_list->view_db.str,
|
||||||
|
table_list->view_name.str);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||||
ER_NO_DEFAULT_FOR_FIELD,
|
ER_NO_DEFAULT_FOR_FIELD,
|
||||||
ER(ER_NO_DEFAULT_FOR_FIELD),
|
ER(ER_NO_DEFAULT_FOR_FIELD),
|
||||||
(*field)->field_name);
|
(*field)->field_name);
|
||||||
|
}
|
||||||
err= 1;
|
err= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1938,7 +1997,6 @@ bool mysql_insert_select_prepare(THD *thd)
|
|||||||
SELECT_LEX do not belong to INSERT statement, so we can't add WHERE
|
SELECT_LEX do not belong to INSERT statement, so we can't add WHERE
|
||||||
clause if table is VIEW
|
clause if table is VIEW
|
||||||
*/
|
*/
|
||||||
lex->query_tables->no_where_clause= 1;
|
|
||||||
if (mysql_prepare_insert(thd, lex->query_tables,
|
if (mysql_prepare_insert(thd, lex->query_tables,
|
||||||
lex->query_tables->table, lex->field_list, 0,
|
lex->query_tables->table, lex->field_list, 0,
|
||||||
lex->update_list, lex->value_list,
|
lex->update_list, lex->value_list,
|
||||||
@ -1988,8 +2046,8 @@ select_insert::select_insert(TABLE_LIST *table_list_par, TABLE *table_par,
|
|||||||
int
|
int
|
||||||
select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
|
select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
|
||||||
{
|
{
|
||||||
int res;
|
|
||||||
LEX *lex= thd->lex;
|
LEX *lex= thd->lex;
|
||||||
|
int res;
|
||||||
SELECT_LEX *lex_current_select_save= lex->current_select;
|
SELECT_LEX *lex_current_select_save= lex->current_select;
|
||||||
DBUG_ENTER("select_insert::prepare");
|
DBUG_ENTER("select_insert::prepare");
|
||||||
|
|
||||||
@ -2043,8 +2101,11 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
|
|||||||
(thd->variables.sql_mode &
|
(thd->variables.sql_mode &
|
||||||
(MODE_STRICT_TRANS_TABLES |
|
(MODE_STRICT_TRANS_TABLES |
|
||||||
MODE_STRICT_ALL_TABLES)));
|
MODE_STRICT_ALL_TABLES)));
|
||||||
DBUG_RETURN(fields->elements &&
|
res= ((fields->elements &&
|
||||||
check_that_all_fields_are_given_values(thd, table));
|
check_that_all_fields_are_given_values(thd, table, table_list)) ||
|
||||||
|
table_list->prepare_where(thd, 0, TRUE) ||
|
||||||
|
table_list->prepare_check_option(thd));
|
||||||
|
DBUG_RETURN(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2290,7 +2351,8 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
|
|||||||
(thd->variables.sql_mode &
|
(thd->variables.sql_mode &
|
||||||
(MODE_STRICT_TRANS_TABLES |
|
(MODE_STRICT_TRANS_TABLES |
|
||||||
MODE_STRICT_ALL_TABLES)));
|
MODE_STRICT_ALL_TABLES)));
|
||||||
DBUG_RETURN(check_that_all_fields_are_given_values(thd, table));
|
DBUG_RETURN(check_that_all_fields_are_given_values(thd, table,
|
||||||
|
table_list));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1104,7 +1104,8 @@ void st_select_lex::init_query()
|
|||||||
having= where= prep_where= 0;
|
having= where= prep_where= 0;
|
||||||
olap= UNSPECIFIED_OLAP_TYPE;
|
olap= UNSPECIFIED_OLAP_TYPE;
|
||||||
having_fix_field= 0;
|
having_fix_field= 0;
|
||||||
resolve_mode= NOMATTER_MODE;
|
context.select_lex= this;
|
||||||
|
context.init();
|
||||||
cond_count= with_wild= 0;
|
cond_count= with_wild= 0;
|
||||||
conds_processed_with_permanent_arena= 0;
|
conds_processed_with_permanent_arena= 0;
|
||||||
ref_pointer_array= 0;
|
ref_pointer_array= 0;
|
||||||
@ -1703,8 +1704,7 @@ bool st_lex::can_not_use_merged()
|
|||||||
|
|
||||||
bool st_lex::only_view_structure()
|
bool st_lex::only_view_structure()
|
||||||
{
|
{
|
||||||
switch(sql_command)
|
switch (sql_command) {
|
||||||
{
|
|
||||||
case SQLCOM_SHOW_CREATE:
|
case SQLCOM_SHOW_CREATE:
|
||||||
case SQLCOM_SHOW_TABLES:
|
case SQLCOM_SHOW_TABLES:
|
||||||
case SQLCOM_SHOW_FIELDS:
|
case SQLCOM_SHOW_FIELDS:
|
||||||
@ -1744,6 +1744,31 @@ bool st_lex::need_correct_ident()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Get effective type of CHECK OPTION for given view
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
get_effective_with_check()
|
||||||
|
view given view
|
||||||
|
|
||||||
|
NOTE
|
||||||
|
It have not sense to set CHECK OPTION for SELECT satement or subqueries,
|
||||||
|
so we do not.
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
VIEW_CHECK_NONE no need CHECK OPTION
|
||||||
|
VIEW_CHECK_LOCAL CHECK OPTION LOCAL
|
||||||
|
VIEW_CHECK_CASCADED CHECK OPTION CASCADED
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint8 st_lex::get_effective_with_check(st_table_list *view)
|
||||||
|
{
|
||||||
|
if (view->select_lex->master_unit() == &unit &&
|
||||||
|
which_check_option_applicable())
|
||||||
|
return (uint8)view->with_check;
|
||||||
|
return VIEW_CHECK_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
initialize limit counters
|
initialize limit counters
|
||||||
@ -1804,7 +1829,8 @@ TABLE_LIST *st_lex::unlink_first_table(bool *link_to_local)
|
|||||||
*/
|
*/
|
||||||
if ((*link_to_local= test(select_lex.table_list.first)))
|
if ((*link_to_local= test(select_lex.table_list.first)))
|
||||||
{
|
{
|
||||||
select_lex.table_list.first= (byte*) first->next_local;
|
select_lex.table_list.first= (byte*) (select_lex.context.table_list=
|
||||||
|
first->next_local);
|
||||||
select_lex.table_list.elements--; //safety
|
select_lex.table_list.elements--; //safety
|
||||||
first->next_local= 0;
|
first->next_local= 0;
|
||||||
/*
|
/*
|
||||||
@ -1909,7 +1935,8 @@ void st_lex::link_first_table_back(TABLE_LIST *first,
|
|||||||
if (link_to_local)
|
if (link_to_local)
|
||||||
{
|
{
|
||||||
first->next_local= (TABLE_LIST*) select_lex.table_list.first;
|
first->next_local= (TABLE_LIST*) select_lex.table_list.first;
|
||||||
select_lex.table_list.first= (byte*) first;
|
select_lex.table_list.first=
|
||||||
|
(byte*) select_lex.context.table_list= first;
|
||||||
select_lex.table_list.elements++; //safety
|
select_lex.table_list.elements++; //safety
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1930,7 +1957,21 @@ void st_select_lex::fix_prepare_information(THD *thd, Item **conds)
|
|||||||
if (!thd->current_arena->is_conventional() && first_execution)
|
if (!thd->current_arena->is_conventional() && first_execution)
|
||||||
{
|
{
|
||||||
first_execution= 0;
|
first_execution= 0;
|
||||||
prep_where= where;
|
if (*conds)
|
||||||
|
{
|
||||||
|
prep_where= *conds;
|
||||||
|
*conds= where= prep_where->copy_andor_structure(thd);
|
||||||
|
}
|
||||||
|
for (TABLE_LIST *tbl= (TABLE_LIST *)table_list.first;
|
||||||
|
tbl;
|
||||||
|
tbl= tbl->next_local)
|
||||||
|
{
|
||||||
|
if (tbl->on_expr)
|
||||||
|
{
|
||||||
|
tbl->prep_on_expr= tbl->on_expr;
|
||||||
|
tbl->on_expr= tbl->on_expr->copy_andor_structure(thd);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1945,3 +1986,4 @@ void st_select_lex::fix_prepare_information(THD *thd, Item **conds)
|
|||||||
st_select_lex_unit::change_result
|
st_select_lex_unit::change_result
|
||||||
are in sql_union.cc
|
are in sql_union.cc
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -470,6 +470,7 @@ typedef class st_select_lex_unit SELECT_LEX_UNIT;
|
|||||||
class st_select_lex: public st_select_lex_node
|
class st_select_lex: public st_select_lex_node
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
Name_resolution_context context;
|
||||||
char *db, *db1, *table1, *db2, *table2; /* For outer join using .. */
|
char *db, *db1, *table1, *db2, *table2; /* For outer join using .. */
|
||||||
Item *where, *having; /* WHERE & HAVING clauses */
|
Item *where, *having; /* WHERE & HAVING clauses */
|
||||||
Item *prep_where; /* saved WHERE clause for prepared statement processing */
|
Item *prep_where; /* saved WHERE clause for prepared statement processing */
|
||||||
@ -549,27 +550,6 @@ public:
|
|||||||
/* exclude this select from check of unique_table() */
|
/* exclude this select from check of unique_table() */
|
||||||
bool exclude_from_table_unique_test;
|
bool exclude_from_table_unique_test;
|
||||||
|
|
||||||
/*
|
|
||||||
SELECT for SELECT command st_select_lex. Used to privent scaning
|
|
||||||
item_list of non-SELECT st_select_lex (no sense find to finding
|
|
||||||
reference in it (all should be in tables, it is dangerouse due
|
|
||||||
to order of fix_fields calling for non-SELECTs commands (item list
|
|
||||||
can be not fix_fieldsd)). This value will be assigned for
|
|
||||||
primary select (sql_yac.yy) and for any subquery and
|
|
||||||
UNION SELECT (sql_parse.cc mysql_new_select())
|
|
||||||
|
|
||||||
|
|
||||||
INSERT for primary st_select_lex structure of simple INSERT/REPLACE
|
|
||||||
(used for name resolution, see Item_fiels & Item_ref fix_fields,
|
|
||||||
FALSE for INSERT/REPLACE ... SELECT, because it's
|
|
||||||
st_select_lex->table_list will be preprocessed (first table removed)
|
|
||||||
before passing to handle_select)
|
|
||||||
|
|
||||||
NOMATTER for other
|
|
||||||
*/
|
|
||||||
enum {NOMATTER_MODE, SELECT_MODE, INSERT_MODE} resolve_mode;
|
|
||||||
|
|
||||||
|
|
||||||
void init_query();
|
void init_query();
|
||||||
void init_select();
|
void init_select();
|
||||||
st_select_lex_unit* master_unit();
|
st_select_lex_unit* master_unit();
|
||||||
@ -903,7 +883,30 @@ typedef struct st_lex
|
|||||||
bool can_not_use_merged();
|
bool can_not_use_merged();
|
||||||
bool only_view_structure();
|
bool only_view_structure();
|
||||||
bool need_correct_ident();
|
bool need_correct_ident();
|
||||||
|
uint8 get_effective_with_check(st_table_list *view);
|
||||||
|
/*
|
||||||
|
Is this update command where 'WHITH CHECK OPTION' clause is important
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
st_lex::which_check_option_applicable()
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
TRUE have to take 'WHITH CHECK OPTION' clause into account
|
||||||
|
FALSE 'WHITH CHECK OPTION' clause do not need
|
||||||
|
*/
|
||||||
|
inline bool which_check_option_applicable()
|
||||||
|
{
|
||||||
|
switch (sql_command) {
|
||||||
|
case SQLCOM_UPDATE:
|
||||||
|
case SQLCOM_UPDATE_MULTI:
|
||||||
|
case SQLCOM_INSERT:
|
||||||
|
case SQLCOM_INSERT_SELECT:
|
||||||
|
case SQLCOM_LOAD:
|
||||||
|
return TRUE;
|
||||||
|
default:
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
inline bool requires_prelocking()
|
inline bool requires_prelocking()
|
||||||
{
|
{
|
||||||
return test(query_tables_own_last);
|
return test(query_tables_own_last);
|
||||||
|
@ -149,7 +149,8 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
|||||||
}
|
}
|
||||||
if (open_and_lock_tables(thd, table_list))
|
if (open_and_lock_tables(thd, table_list))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
if (setup_tables(thd, table_list, &unused_conds,
|
if (setup_tables(thd, &thd->lex->select_lex.context,
|
||||||
|
table_list, &unused_conds,
|
||||||
&thd->lex->select_lex.leaf_tables, FALSE))
|
&thd->lex->select_lex.leaf_tables, FALSE))
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
if (!table_list->table || // do not suport join view
|
if (!table_list->table || // do not suport join view
|
||||||
@ -159,6 +160,11 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
|||||||
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "LOAD");
|
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "LOAD");
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
}
|
}
|
||||||
|
if (table_list->prepare_where(thd, 0, TRUE) ||
|
||||||
|
table_list->prepare_check_option(thd))
|
||||||
|
{
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
Let us emit an error if we are loading data to table which is used
|
Let us emit an error if we are loading data to table which is used
|
||||||
in subselect in SET clause like we do it for INSERT.
|
in subselect in SET clause like we do it for INSERT.
|
||||||
@ -186,16 +192,16 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
|||||||
Let us also prepare SET clause, altough it is probably empty
|
Let us also prepare SET clause, altough it is probably empty
|
||||||
in this case.
|
in this case.
|
||||||
*/
|
*/
|
||||||
if (setup_fields(thd, 0, table_list, set_fields, 1, 0, 0) ||
|
if (setup_fields(thd, 0, set_fields, 1, 0, 0) ||
|
||||||
setup_fields(thd, 0, table_list, set_values, 1, 0, 0))
|
setup_fields(thd, 0, set_values, 1, 0, 0))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // Part field list
|
{ // Part field list
|
||||||
/* TODO: use this conds for 'WITH CHECK OPTIONS' */
|
/* TODO: use this conds for 'WITH CHECK OPTIONS' */
|
||||||
if (setup_fields(thd, 0, table_list, fields_vars, 1, 0, 0) ||
|
if (setup_fields(thd, 0, fields_vars, 1, 0, 0) ||
|
||||||
setup_fields(thd, 0, table_list, set_fields, 1, 0, 0) ||
|
setup_fields(thd, 0, set_fields, 1, 0, 0) ||
|
||||||
check_that_all_fields_are_given_values(thd, table))
|
check_that_all_fields_are_given_values(thd, table, table_list))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
/*
|
/*
|
||||||
Check whenever TIMESTAMP field with auto-set feature specified
|
Check whenever TIMESTAMP field with auto-set feature specified
|
||||||
@ -209,7 +215,7 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
|||||||
check_that_all_fields_are_given_values() and setting use_timestamp
|
check_that_all_fields_are_given_values() and setting use_timestamp
|
||||||
since it may update query_id for some fields.
|
since it may update query_id for some fields.
|
||||||
*/
|
*/
|
||||||
if (setup_fields(thd, 0, table_list, set_values, 1, 0, 0))
|
if (setup_fields(thd, 0, set_values, 1, 0, 0))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,7 +77,8 @@ static int make_new_olap_select(LEX *lex, SELECT_LEX *select_lex, List<Item> new
|
|||||||
{
|
{
|
||||||
not_found= 0;
|
not_found= 0;
|
||||||
((Item_field*)new_item)->db_name=iif->db_name;
|
((Item_field*)new_item)->db_name=iif->db_name;
|
||||||
Item_field *new_one=new Item_field(iif->db_name, iif->table_name, iif->field_name);
|
Item_field *new_one=new Item_field(&select_lex->context,
|
||||||
|
iif->db_name, iif->table_name, iif->field_name);
|
||||||
privlist.push_back(new_one);
|
privlist.push_back(new_one);
|
||||||
if (add_to_list(new_select->group_list,new_one,1))
|
if (add_to_list(new_select->group_list,new_one,1))
|
||||||
return 1;
|
return 1;
|
||||||
@ -152,12 +153,11 @@ int handle_olaps(LEX *lex, SELECT_LEX *select_lex)
|
|||||||
List<Item> all_fields(select_lex->item_list);
|
List<Item> all_fields(select_lex->item_list);
|
||||||
|
|
||||||
|
|
||||||
if (setup_tables(lex->thd, (TABLE_LIST *)select_lex->table_list.first
|
if (setup_tables(lex->thd, &select_lex->context,
|
||||||
|
(TABLE_LIST *)select_lex->table_list.first
|
||||||
&select_lex->where, &select_lex->leaf_tables, FALSE) ||
|
&select_lex->where, &select_lex->leaf_tables, FALSE) ||
|
||||||
setup_fields(lex->thd, 0, (TABLE_LIST *)select_lex->table_list.first,
|
setup_fields(lex->thd, 0, select_lex->item_list, 1, &all_fields,1) ||
|
||||||
select_lex->item_list, 1, &all_fields,1) ||
|
setup_fields(lex->thd, 0, item_list_copy, 1, &all_fields, 1))
|
||||||
setup_fields(lex->thd, 0, (TABLE_LIST *)select_lex->table_list.first,
|
|
||||||
item_list_copy, 1, &all_fields, 1))
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (select_lex->olap == CUBE_TYPE)
|
if (select_lex->olap == CUBE_TYPE)
|
||||||
|
@ -2289,6 +2289,10 @@ mysql_execute_command(THD *thd)
|
|||||||
lex->first_lists_tables_same();
|
lex->first_lists_tables_same();
|
||||||
/* should be assigned after making first tables same */
|
/* should be assigned after making first tables same */
|
||||||
all_tables= lex->query_tables;
|
all_tables= lex->query_tables;
|
||||||
|
/* set context for commands which do not use setup_tables */
|
||||||
|
select_lex->
|
||||||
|
context.resolve_in_table_list_only((TABLE_LIST*)select_lex->
|
||||||
|
table_list.first);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Reset warning count for each query that uses tables
|
Reset warning count for each query that uses tables
|
||||||
@ -2572,7 +2576,7 @@ mysql_execute_command(THD *thd)
|
|||||||
goto error;
|
goto error;
|
||||||
/* PURGE MASTER LOGS BEFORE 'data' */
|
/* PURGE MASTER LOGS BEFORE 'data' */
|
||||||
it= (Item *)lex->value_list.head();
|
it= (Item *)lex->value_list.head();
|
||||||
if ((!it->fixed &&it->fix_fields(lex->thd, 0, &it)) ||
|
if ((!it->fixed && it->fix_fields(lex->thd, &it)) ||
|
||||||
it->check_cols(1))
|
it->check_cols(1))
|
||||||
{
|
{
|
||||||
my_error(ER_WRONG_ARGUMENTS, MYF(0), "PURGE LOGS BEFORE");
|
my_error(ER_WRONG_ARGUMENTS, MYF(0), "PURGE LOGS BEFORE");
|
||||||
@ -2881,9 +2885,7 @@ mysql_execute_command(THD *thd)
|
|||||||
CREATE from SELECT give its SELECT_LEX for SELECT,
|
CREATE from SELECT give its SELECT_LEX for SELECT,
|
||||||
and item_list belong to SELECT
|
and item_list belong to SELECT
|
||||||
*/
|
*/
|
||||||
select_lex->resolve_mode= SELECT_LEX::SELECT_MODE;
|
|
||||||
res= handle_select(thd, lex, result, 0);
|
res= handle_select(thd, lex, result, 0);
|
||||||
select_lex->resolve_mode= SELECT_LEX::NOMATTER_MODE;
|
|
||||||
delete result;
|
delete result;
|
||||||
}
|
}
|
||||||
/* reset for PS */
|
/* reset for PS */
|
||||||
@ -3222,6 +3224,8 @@ end_with_restore_list:
|
|||||||
DBUG_ASSERT(first_table == all_tables && first_table != 0);
|
DBUG_ASSERT(first_table == all_tables && first_table != 0);
|
||||||
if ((res= insert_precheck(thd, all_tables)))
|
if ((res= insert_precheck(thd, all_tables)))
|
||||||
break;
|
break;
|
||||||
|
/* Skip first table, which is the table we are inserting in */
|
||||||
|
select_lex->context.table_list= first_table->next_local;
|
||||||
res= mysql_insert(thd, all_tables, lex->field_list, lex->many_values,
|
res= mysql_insert(thd, all_tables, lex->field_list, lex->many_values,
|
||||||
lex->update_list, lex->value_list,
|
lex->update_list, lex->value_list,
|
||||||
lex->duplicates, lex->ignore);
|
lex->duplicates, lex->ignore);
|
||||||
@ -3252,18 +3256,17 @@ end_with_restore_list:
|
|||||||
select_lex->table_list.first= (byte*)first_table->next_local;
|
select_lex->table_list.first= (byte*)first_table->next_local;
|
||||||
|
|
||||||
res= mysql_insert_select_prepare(thd);
|
res= mysql_insert_select_prepare(thd);
|
||||||
|
lex->select_lex.context.table_list= first_table->next_local;
|
||||||
if (!res && (result= new select_insert(first_table, first_table->table,
|
if (!res && (result= new select_insert(first_table, first_table->table,
|
||||||
&lex->field_list,
|
&lex->field_list,
|
||||||
&lex->update_list, &lex->value_list,
|
&lex->update_list,
|
||||||
|
&lex->value_list,
|
||||||
lex->duplicates, lex->ignore)))
|
lex->duplicates, lex->ignore)))
|
||||||
{
|
{
|
||||||
/*
|
/* Skip first table, which is the table we are inserting in */
|
||||||
insert/replace from SELECT give its SELECT_LEX for SELECT,
|
select_lex->context.table_list= first_table->next_local;
|
||||||
and item_list belong to SELECT
|
|
||||||
*/
|
|
||||||
select_lex->resolve_mode= SELECT_LEX::SELECT_MODE;
|
|
||||||
res= handle_select(thd, lex, result, OPTION_SETUP_TABLES_DONE);
|
res= handle_select(thd, lex, result, OPTION_SETUP_TABLES_DONE);
|
||||||
select_lex->resolve_mode= SELECT_LEX::INSERT_MODE;
|
|
||||||
delete result;
|
delete result;
|
||||||
}
|
}
|
||||||
/* revert changes for SP */
|
/* revert changes for SP */
|
||||||
@ -3863,7 +3866,7 @@ end_with_restore_list:
|
|||||||
{
|
{
|
||||||
Item *it= (Item *)lex->value_list.head();
|
Item *it= (Item *)lex->value_list.head();
|
||||||
|
|
||||||
if ((!it->fixed && it->fix_fields(lex->thd, 0, &it)) || it->check_cols(1))
|
if ((!it->fixed && it->fix_fields(lex->thd, &it)) || it->check_cols(1))
|
||||||
{
|
{
|
||||||
my_message(ER_SET_CONSTANTS_ONLY, ER(ER_SET_CONSTANTS_ONLY),
|
my_message(ER_SET_CONSTANTS_ONLY, ER(ER_SET_CONSTANTS_ONLY),
|
||||||
MYF(0));
|
MYF(0));
|
||||||
@ -5230,16 +5233,27 @@ mysql_new_select(LEX *lex, bool move_down)
|
|||||||
unit->link_prev= 0;
|
unit->link_prev= 0;
|
||||||
unit->return_to= lex->current_select;
|
unit->return_to= lex->current_select;
|
||||||
select_lex->include_down(unit);
|
select_lex->include_down(unit);
|
||||||
/* TODO: assign resolve_mode for fake subquery after merging with new tree */
|
/*
|
||||||
|
By default we assume that it is usual subselect and we have outer name
|
||||||
|
resolution context, if no we will assign it to 0 later
|
||||||
|
*/
|
||||||
|
select_lex->context.outer_context= &select_lex->outer_select()->context;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
Name_resolution_context *outer_context;
|
||||||
if (lex->current_select->order_list.first && !lex->current_select->braces)
|
if (lex->current_select->order_list.first && !lex->current_select->braces)
|
||||||
{
|
{
|
||||||
my_error(ER_WRONG_USAGE, MYF(0), "UNION", "ORDER BY");
|
my_error(ER_WRONG_USAGE, MYF(0), "UNION", "ORDER BY");
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
select_lex->include_neighbour(lex->current_select);
|
select_lex->include_neighbour(lex->current_select);
|
||||||
|
/*
|
||||||
|
we are not sure that we have one level of SELECTs above, so we take
|
||||||
|
outer_context address from first select of unit
|
||||||
|
*/
|
||||||
|
outer_context=
|
||||||
|
select_lex->master_unit()->first_select()->context.outer_context;
|
||||||
SELECT_LEX_UNIT *unit= select_lex->master_unit();
|
SELECT_LEX_UNIT *unit= select_lex->master_unit();
|
||||||
SELECT_LEX *fake= unit->fake_select_lex;
|
SELECT_LEX *fake= unit->fake_select_lex;
|
||||||
if (!fake)
|
if (!fake)
|
||||||
@ -5256,13 +5270,23 @@ mysql_new_select(LEX *lex, bool move_down)
|
|||||||
fake->make_empty_select();
|
fake->make_empty_select();
|
||||||
fake->linkage= GLOBAL_OPTIONS_TYPE;
|
fake->linkage= GLOBAL_OPTIONS_TYPE;
|
||||||
fake->select_limit= 0;
|
fake->select_limit= 0;
|
||||||
|
|
||||||
|
fake->context.outer_context= outer_context;
|
||||||
|
/* allow item list resolving in fake select for ORDER BY */
|
||||||
|
fake->context.resolve_in_select_list= TRUE;
|
||||||
|
fake->context.select_lex= fake;
|
||||||
}
|
}
|
||||||
|
select_lex->context.outer_context= outer_context;
|
||||||
}
|
}
|
||||||
|
|
||||||
select_lex->master_unit()->global_parameters= select_lex;
|
select_lex->master_unit()->global_parameters= select_lex;
|
||||||
select_lex->include_global((st_select_lex_node**)&lex->all_selects_list);
|
select_lex->include_global((st_select_lex_node**)&lex->all_selects_list);
|
||||||
lex->current_select= select_lex;
|
lex->current_select= select_lex;
|
||||||
select_lex->resolve_mode= SELECT_LEX::SELECT_MODE;
|
/*
|
||||||
|
in subquery is SELECT query and we allow resolution of names in SELECT
|
||||||
|
list
|
||||||
|
*/
|
||||||
|
select_lex->context.resolve_in_select_list= TRUE;
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -963,7 +963,7 @@ static bool mysql_test_insert(Prepared_statement *stmt,
|
|||||||
my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), counter);
|
my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), counter);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (setup_fields(thd, 0, table_list, *values, 0, 0, 0))
|
if (setup_fields(thd, 0, *values, 0, 0, 0))
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1039,9 +1039,9 @@ static int mysql_test_update(Prepared_statement *stmt,
|
|||||||
table_list->grant.want_privilege= want_privilege;
|
table_list->grant.want_privilege= want_privilege;
|
||||||
table_list->table->grant.want_privilege= want_privilege;
|
table_list->table->grant.want_privilege= want_privilege;
|
||||||
#endif
|
#endif
|
||||||
thd->lex->select_lex.no_wrap_view_item= 1;
|
thd->lex->select_lex.no_wrap_view_item= TRUE;
|
||||||
res= setup_fields(thd, 0, table_list, select->item_list, 1, 0, 0);
|
res= setup_fields(thd, 0, select->item_list, 1, 0, 0);
|
||||||
thd->lex->select_lex.no_wrap_view_item= 0;
|
thd->lex->select_lex.no_wrap_view_item= FALSE;
|
||||||
if (res)
|
if (res)
|
||||||
goto error;
|
goto error;
|
||||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||||
@ -1050,7 +1050,7 @@ static int mysql_test_update(Prepared_statement *stmt,
|
|||||||
table_list->table->grant.want_privilege=
|
table_list->table->grant.want_privilege=
|
||||||
(SELECT_ACL & ~table_list->table->grant.privilege);
|
(SELECT_ACL & ~table_list->table->grant.privilege);
|
||||||
#endif
|
#endif
|
||||||
if (setup_fields(thd, 0, table_list, stmt->lex->value_list, 0, 0, 0))
|
if (setup_fields(thd, 0, stmt->lex->value_list, 0, 0, 0))
|
||||||
goto error;
|
goto error;
|
||||||
/* TODO: here we should send types of placeholders to the client. */
|
/* TODO: here we should send types of placeholders to the client. */
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
@ -1119,6 +1119,8 @@ static bool mysql_test_select(Prepared_statement *stmt,
|
|||||||
SELECT_LEX_UNIT *unit= &lex->unit;
|
SELECT_LEX_UNIT *unit= &lex->unit;
|
||||||
DBUG_ENTER("mysql_test_select");
|
DBUG_ENTER("mysql_test_select");
|
||||||
|
|
||||||
|
lex->select_lex.context.resolve_in_select_list= TRUE;
|
||||||
|
|
||||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||||
ulong privilege= lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL;
|
ulong privilege= lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL;
|
||||||
if (tables)
|
if (tables)
|
||||||
@ -1207,7 +1209,7 @@ static bool mysql_test_do_fields(Prepared_statement *stmt,
|
|||||||
|
|
||||||
if (open_and_lock_tables(thd, tables))
|
if (open_and_lock_tables(thd, tables))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
DBUG_RETURN(setup_fields(thd, 0, 0, *values, 0, 0, 0));
|
DBUG_RETURN(setup_fields(thd, 0, *values, 0, 0, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1277,6 +1279,8 @@ static bool select_like_stmt_test(Prepared_statement *stmt,
|
|||||||
THD *thd= stmt->thd;
|
THD *thd= stmt->thd;
|
||||||
LEX *lex= stmt->lex;
|
LEX *lex= stmt->lex;
|
||||||
|
|
||||||
|
lex->select_lex.context.resolve_in_select_list= TRUE;
|
||||||
|
|
||||||
if (specific_prepare && (*specific_prepare)(thd))
|
if (specific_prepare && (*specific_prepare)(thd))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
@ -1354,9 +1358,8 @@ static bool mysql_test_create_table(Prepared_statement *stmt)
|
|||||||
|
|
||||||
if (select_lex->item_list.elements)
|
if (select_lex->item_list.elements)
|
||||||
{
|
{
|
||||||
select_lex->resolve_mode= SELECT_LEX::SELECT_MODE;
|
select_lex->context.resolve_in_select_list= TRUE;
|
||||||
res= select_like_stmt_test_with_open_n_lock(stmt, tables, 0, 0);
|
res= select_like_stmt_test_with_open_n_lock(stmt, tables, 0, 0);
|
||||||
select_lex->resolve_mode= SELECT_LEX::NOMATTER_MODE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* put tables back for PS rexecuting */
|
/* put tables back for PS rexecuting */
|
||||||
@ -1446,16 +1449,21 @@ error:
|
|||||||
|
|
||||||
static bool mysql_insert_select_prepare_tester(THD *thd)
|
static bool mysql_insert_select_prepare_tester(THD *thd)
|
||||||
{
|
{
|
||||||
|
TABLE_LIST *first;
|
||||||
|
bool res;
|
||||||
SELECT_LEX *first_select= &thd->lex->select_lex;
|
SELECT_LEX *first_select= &thd->lex->select_lex;
|
||||||
/* Skip first table, which is the table we are inserting in */
|
/* Skip first table, which is the table we are inserting in */
|
||||||
first_select->table_list.first= (byte*)((TABLE_LIST*)first_select->
|
first_select->table_list.first= (byte*)(first=
|
||||||
table_list.first)->next_local;
|
((TABLE_LIST*)first_select->
|
||||||
|
table_list.first)->next_local);
|
||||||
|
res= mysql_insert_select_prepare(thd);
|
||||||
/*
|
/*
|
||||||
insert/replace from SELECT give its SELECT_LEX for SELECT,
|
insert/replace from SELECT give its SELECT_LEX for SELECT,
|
||||||
and item_list belong to SELECT
|
and item_list belong to SELECT
|
||||||
*/
|
*/
|
||||||
first_select->resolve_mode= SELECT_LEX::SELECT_MODE;
|
thd->lex->select_lex.context.resolve_in_select_list= TRUE;
|
||||||
return mysql_insert_select_prepare(thd);
|
thd->lex->select_lex.context.table_list= first;
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1493,12 +1501,12 @@ static int mysql_test_insert_select(Prepared_statement *stmt,
|
|||||||
first_local_table= (TABLE_LIST *)lex->select_lex.table_list.first;
|
first_local_table= (TABLE_LIST *)lex->select_lex.table_list.first;
|
||||||
DBUG_ASSERT(first_local_table != 0);
|
DBUG_ASSERT(first_local_table != 0);
|
||||||
|
|
||||||
res= select_like_stmt_test_with_open_n_lock(stmt, tables,
|
res=
|
||||||
|
select_like_stmt_test_with_open_n_lock(stmt, tables,
|
||||||
&mysql_insert_select_prepare_tester,
|
&mysql_insert_select_prepare_tester,
|
||||||
OPTION_SETUP_TABLES_DONE);
|
OPTION_SETUP_TABLES_DONE);
|
||||||
/* revert changes made by mysql_insert_select_prepare_tester */
|
/* revert changes made by mysql_insert_select_prepare_tester */
|
||||||
lex->select_lex.table_list.first= (byte*) first_local_table;
|
lex->select_lex.table_list.first= (byte*) first_local_table;
|
||||||
lex->select_lex.resolve_mode= SELECT_LEX::INSERT_MODE;
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1538,6 +1546,10 @@ static bool check_prepared_statement(Prepared_statement *stmt,
|
|||||||
lex->first_lists_tables_same();
|
lex->first_lists_tables_same();
|
||||||
tables= lex->query_tables;
|
tables= lex->query_tables;
|
||||||
|
|
||||||
|
/* set context for commands which do not use setup_tables */
|
||||||
|
lex->select_lex.context.resolve_in_table_list_only(select_lex->
|
||||||
|
get_table_list());
|
||||||
|
|
||||||
switch (sql_command) {
|
switch (sql_command) {
|
||||||
case SQLCOM_REPLACE:
|
case SQLCOM_REPLACE:
|
||||||
case SQLCOM_INSERT:
|
case SQLCOM_INSERT:
|
||||||
@ -1813,18 +1825,9 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length,
|
|||||||
void init_stmt_after_parse(THD *thd, LEX *lex)
|
void init_stmt_after_parse(THD *thd, LEX *lex)
|
||||||
{
|
{
|
||||||
SELECT_LEX *sl= lex->all_selects_list;
|
SELECT_LEX *sl= lex->all_selects_list;
|
||||||
/*
|
|
||||||
Save WHERE clause pointers, because they may be changed during query
|
|
||||||
optimisation.
|
|
||||||
*/
|
|
||||||
for (; sl; sl= sl->next_select_in_list())
|
|
||||||
{
|
|
||||||
sl->prep_where= sl->where;
|
|
||||||
sl->uncacheable&= ~UNCACHEABLE_PREPARE;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (TABLE_LIST *table= lex->query_tables; table; table= table->next_global)
|
for (; sl; sl= sl->next_select_in_list())
|
||||||
table->prep_on_expr= table->on_expr;
|
sl->uncacheable&= ~UNCACHEABLE_PREPARE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -182,7 +182,7 @@ static void reset_cache_read(JOIN_CACHE *cache);
|
|||||||
static void reset_cache_write(JOIN_CACHE *cache);
|
static void reset_cache_write(JOIN_CACHE *cache);
|
||||||
static void read_cached_record(JOIN_TAB *tab);
|
static void read_cached_record(JOIN_TAB *tab);
|
||||||
static bool cmp_buffer_with_ref(JOIN_TAB *tab);
|
static bool cmp_buffer_with_ref(JOIN_TAB *tab);
|
||||||
static bool setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields,
|
static bool setup_new_fields(THD *thd, List<Item> &fields,
|
||||||
List<Item> &all_fields, ORDER *new_order);
|
List<Item> &all_fields, ORDER *new_order);
|
||||||
static ORDER *create_distinct_group(THD *thd, ORDER *order,
|
static ORDER *create_distinct_group(THD *thd, ORDER *order,
|
||||||
List<Item> &fields,
|
List<Item> &fields,
|
||||||
@ -283,6 +283,7 @@ inline int setup_without_group(THD *thd, Item **ref_pointer_array,
|
|||||||
save_allow_sum_func= thd->allow_sum_func;
|
save_allow_sum_func= thd->allow_sum_func;
|
||||||
thd->allow_sum_func= 0;
|
thd->allow_sum_func= 0;
|
||||||
res= setup_conds(thd, tables, leaves, conds);
|
res= setup_conds(thd, tables, leaves, conds);
|
||||||
|
|
||||||
thd->allow_sum_func= save_allow_sum_func;
|
thd->allow_sum_func= save_allow_sum_func;
|
||||||
res= res || setup_order(thd, ref_pointer_array, tables, fields, all_fields,
|
res= res || setup_order(thd, ref_pointer_array, tables, fields, all_fields,
|
||||||
order);
|
order);
|
||||||
@ -339,11 +340,12 @@ JOIN::prepare(Item ***rref_pointer_array,
|
|||||||
/* Check that all tables, fields, conds and order are ok */
|
/* Check that all tables, fields, conds and order are ok */
|
||||||
|
|
||||||
if ((!(select_options & OPTION_SETUP_TABLES_DONE) &&
|
if ((!(select_options & OPTION_SETUP_TABLES_DONE) &&
|
||||||
setup_tables(thd, tables_list, &conds, &select_lex->leaf_tables,
|
setup_tables(thd, &select_lex->context,
|
||||||
|
tables_list, &conds, &select_lex->leaf_tables,
|
||||||
FALSE)) ||
|
FALSE)) ||
|
||||||
setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) ||
|
setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) ||
|
||||||
select_lex->setup_ref_array(thd, og_num) ||
|
select_lex->setup_ref_array(thd, og_num) ||
|
||||||
setup_fields(thd, (*rref_pointer_array), tables_list, fields_list, 1,
|
setup_fields(thd, (*rref_pointer_array), fields_list, 1,
|
||||||
&all_fields, 1) ||
|
&all_fields, 1) ||
|
||||||
setup_without_group(thd, (*rref_pointer_array), tables_list,
|
setup_without_group(thd, (*rref_pointer_array), tables_list,
|
||||||
select_lex->leaf_tables, fields_list,
|
select_lex->leaf_tables, fields_list,
|
||||||
@ -359,7 +361,7 @@ JOIN::prepare(Item ***rref_pointer_array,
|
|||||||
thd->allow_sum_func=1;
|
thd->allow_sum_func=1;
|
||||||
select_lex->having_fix_field= 1;
|
select_lex->having_fix_field= 1;
|
||||||
bool having_fix_rc= (!having->fixed &&
|
bool having_fix_rc= (!having->fixed &&
|
||||||
(having->fix_fields(thd, tables_list, &having) ||
|
(having->fix_fields(thd, &having) ||
|
||||||
having->check_cols(1)));
|
having->check_cols(1)));
|
||||||
select_lex->having_fix_field= 0;
|
select_lex->having_fix_field= 0;
|
||||||
if (having_fix_rc || thd->net.report_error)
|
if (having_fix_rc || thd->net.report_error)
|
||||||
@ -432,7 +434,7 @@ JOIN::prepare(Item ***rref_pointer_array,
|
|||||||
goto err; /* purecov: inspected */
|
goto err; /* purecov: inspected */
|
||||||
if (procedure)
|
if (procedure)
|
||||||
{
|
{
|
||||||
if (setup_new_fields(thd, tables_list, fields_list, all_fields,
|
if (setup_new_fields(thd, fields_list, all_fields,
|
||||||
procedure->param_fields))
|
procedure->param_fields))
|
||||||
goto err; /* purecov: inspected */
|
goto err; /* purecov: inspected */
|
||||||
if (procedure->group)
|
if (procedure->group)
|
||||||
@ -566,7 +568,7 @@ JOIN::optimize()
|
|||||||
Item_cond_and can't be fixed after creation, so we do not check
|
Item_cond_and can't be fixed after creation, so we do not check
|
||||||
conds->fixed
|
conds->fixed
|
||||||
*/
|
*/
|
||||||
conds->fix_fields(thd, tables_list, &conds);
|
conds->fix_fields(thd, &conds);
|
||||||
conds->change_ref_to_fields(thd, tables_list);
|
conds->change_ref_to_fields(thd, tables_list);
|
||||||
conds->top_level_item();
|
conds->top_level_item();
|
||||||
having= 0;
|
having= 0;
|
||||||
@ -1117,7 +1119,6 @@ int
|
|||||||
JOIN::reinit()
|
JOIN::reinit()
|
||||||
{
|
{
|
||||||
DBUG_ENTER("JOIN::reinit");
|
DBUG_ENTER("JOIN::reinit");
|
||||||
|
|
||||||
first_record= 0;
|
first_record= 0;
|
||||||
|
|
||||||
if (exec_tmp_table1)
|
if (exec_tmp_table1)
|
||||||
@ -1977,6 +1978,7 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
|
|||||||
bool free_join= 1;
|
bool free_join= 1;
|
||||||
DBUG_ENTER("mysql_select");
|
DBUG_ENTER("mysql_select");
|
||||||
|
|
||||||
|
select_lex->context.resolve_in_select_list= TRUE;
|
||||||
JOIN *join;
|
JOIN *join;
|
||||||
if (select_lex->join != 0)
|
if (select_lex->join != 0)
|
||||||
{
|
{
|
||||||
@ -7445,7 +7447,7 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top)
|
|||||||
conds->top_level_item();
|
conds->top_level_item();
|
||||||
/* conds is always a new item as both cond and on_expr existed */
|
/* conds is always a new item as both cond and on_expr existed */
|
||||||
DBUG_ASSERT(!conds->fixed);
|
DBUG_ASSERT(!conds->fixed);
|
||||||
conds->fix_fields(join->thd, 0, &conds);
|
conds->fix_fields(join->thd, &conds);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
conds= table->on_expr;
|
conds= table->on_expr;
|
||||||
@ -7666,7 +7668,7 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value)
|
|||||||
cond->fixed, also it do not need tables so we use 0 as second
|
cond->fixed, also it do not need tables so we use 0 as second
|
||||||
argument.
|
argument.
|
||||||
*/
|
*/
|
||||||
cond->fix_fields(thd, 0, &cond);
|
cond->fix_fields(thd, &cond);
|
||||||
}
|
}
|
||||||
thd->insert_id(0); // Clear for next request
|
thd->insert_id(0); // Clear for next request
|
||||||
}
|
}
|
||||||
@ -7685,7 +7687,7 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value)
|
|||||||
cond->fixed, also it do not need tables so we use 0 as second
|
cond->fixed, also it do not need tables so we use 0 as second
|
||||||
argument.
|
argument.
|
||||||
*/
|
*/
|
||||||
cond->fix_fields(thd, 0, &cond);
|
cond->fix_fields(thd, &cond);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -8208,6 +8210,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
|
|||||||
*blob_field++= (uint) (reg_field - table->field);
|
*blob_field++= (uint) (reg_field - table->field);
|
||||||
blob_count++;
|
blob_count++;
|
||||||
}
|
}
|
||||||
|
new_field->field_index= (uint) (reg_field - table->field);
|
||||||
*(reg_field++)= new_field;
|
*(reg_field++)= new_field;
|
||||||
if (new_field->real_type() == MYSQL_TYPE_STRING ||
|
if (new_field->real_type() == MYSQL_TYPE_STRING ||
|
||||||
new_field->real_type() == MYSQL_TYPE_VARCHAR)
|
new_field->real_type() == MYSQL_TYPE_VARCHAR)
|
||||||
@ -8273,6 +8276,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
|
|||||||
new_field->flags|= GROUP_FLAG;
|
new_field->flags|= GROUP_FLAG;
|
||||||
}
|
}
|
||||||
new_field->query_id= thd->query_id;
|
new_field->query_id= thd->query_id;
|
||||||
|
new_field->field_index= (uint) (reg_field - table->field);
|
||||||
*(reg_field++) =new_field;
|
*(reg_field++) =new_field;
|
||||||
}
|
}
|
||||||
if (!--hidden_field_count)
|
if (!--hidden_field_count)
|
||||||
@ -11181,8 +11185,7 @@ static bool fix_having(JOIN *join, Item **having)
|
|||||||
else // This should never happen
|
else // This should never happen
|
||||||
if (!(table->select->cond= new Item_cond_and(table->select->cond,
|
if (!(table->select->cond= new Item_cond_and(table->select->cond,
|
||||||
sort_table_cond)) ||
|
sort_table_cond)) ||
|
||||||
table->select->cond->fix_fields(join->thd, join->tables_list,
|
table->select->cond->fix_fields(join->thd, &table->select->cond))
|
||||||
&table->select->cond))
|
|
||||||
return 1;
|
return 1;
|
||||||
table->select_cond=table->select->cond;
|
table->select_cond=table->select->cond;
|
||||||
table->select_cond->top_level_item();
|
table->select_cond->top_level_item();
|
||||||
@ -11873,8 +11876,8 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
|
|||||||
original field name, we should additionaly check if we have conflict
|
original field name, we should additionaly check if we have conflict
|
||||||
for this name (in case if we would perform lookup in all tables).
|
for this name (in case if we would perform lookup in all tables).
|
||||||
*/
|
*/
|
||||||
if (unaliased && !order_item->fixed && order_item->fix_fields(thd, tables,
|
if (unaliased && !order_item->fixed &&
|
||||||
order->item))
|
order_item->fix_fields(thd, order->item))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
/* Lookup the current GROUP field in the FROM clause. */
|
/* Lookup the current GROUP field in the FROM clause. */
|
||||||
@ -11941,7 +11944,7 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
|
|||||||
arguments for which fix_fields already was called.
|
arguments for which fix_fields already was called.
|
||||||
*/
|
*/
|
||||||
if (!order_item->fixed &&
|
if (!order_item->fixed &&
|
||||||
(order_item->fix_fields(thd, tables, order->item) ||
|
(order_item->fix_fields(thd, order->item) ||
|
||||||
(order_item= *order->item)->check_cols(1) ||
|
(order_item= *order->item)->check_cols(1) ||
|
||||||
thd->is_fatal_error))
|
thd->is_fatal_error))
|
||||||
return TRUE; /* Wrong field. */
|
return TRUE; /* Wrong field. */
|
||||||
@ -12053,7 +12056,7 @@ setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields,
|
setup_new_fields(THD *thd, List<Item> &fields,
|
||||||
List<Item> &all_fields, ORDER *new_field)
|
List<Item> &all_fields, ORDER *new_field)
|
||||||
{
|
{
|
||||||
Item **item;
|
Item **item;
|
||||||
@ -12070,7 +12073,7 @@ setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
thd->where="procedure list";
|
thd->where="procedure list";
|
||||||
if ((*new_field->item)->fix_fields(thd, tables, new_field->item))
|
if ((*new_field->item)->fix_fields(thd, new_field->item))
|
||||||
DBUG_RETURN(1); /* purecov: inspected */
|
DBUG_RETURN(1); /* purecov: inspected */
|
||||||
all_fields.push_front(*new_field->item);
|
all_fields.push_front(*new_field->item);
|
||||||
new_field->item=all_fields.head_ref();
|
new_field->item=all_fields.head_ref();
|
||||||
@ -12868,7 +12871,7 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab)
|
|||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
if (!cond->fixed)
|
if (!cond->fixed)
|
||||||
cond->fix_fields(thd,(TABLE_LIST *) 0, (Item**)&cond);
|
cond->fix_fields(thd, (Item**)&cond);
|
||||||
if (join_tab->select)
|
if (join_tab->select)
|
||||||
{
|
{
|
||||||
error=(int) cond->add(join_tab->select->cond);
|
error=(int) cond->add(join_tab->select->cond);
|
||||||
@ -12940,6 +12943,7 @@ static bool change_group_ref(THD *thd, Item_func *expr, ORDER *group_list,
|
|||||||
{
|
{
|
||||||
if (expr->arg_count)
|
if (expr->arg_count)
|
||||||
{
|
{
|
||||||
|
Name_resolution_context *context= &thd->lex->current_select->context;
|
||||||
Item **arg,**arg_end;
|
Item **arg,**arg_end;
|
||||||
for (arg= expr->arguments(),
|
for (arg= expr->arguments(),
|
||||||
arg_end= expr->arguments()+expr->arg_count;
|
arg_end= expr->arguments()+expr->arg_count;
|
||||||
@ -12954,7 +12958,8 @@ static bool change_group_ref(THD *thd, Item_func *expr, ORDER *group_list,
|
|||||||
if (item->eq(*group_tmp->item,0))
|
if (item->eq(*group_tmp->item,0))
|
||||||
{
|
{
|
||||||
Item *new_item;
|
Item *new_item;
|
||||||
if(!(new_item= new Item_ref(group_tmp->item, 0, item->name)))
|
if(!(new_item= new Item_ref(context, group_tmp->item, 0,
|
||||||
|
item->name)))
|
||||||
return 1; // fatal_error is set
|
return 1; // fatal_error is set
|
||||||
thd->change_item_tree(arg, new_item);
|
thd->change_item_tree(arg, new_item);
|
||||||
*changed= TRUE;
|
*changed= TRUE;
|
||||||
|
@ -3240,11 +3240,13 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list)
|
|||||||
int make_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
|
int make_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
|
||||||
{
|
{
|
||||||
ST_FIELD_INFO *field_info= schema_table->fields_info;
|
ST_FIELD_INFO *field_info= schema_table->fields_info;
|
||||||
|
Name_resolution_context *context= &thd->lex->select_lex.context;
|
||||||
for ( ; field_info->field_name; field_info++)
|
for ( ; field_info->field_name; field_info++)
|
||||||
{
|
{
|
||||||
if (field_info->old_name)
|
if (field_info->old_name)
|
||||||
{
|
{
|
||||||
Item_field *field= new Item_field(NullS, NullS, field_info->field_name);
|
Item_field *field= new Item_field(context,
|
||||||
|
NullS, NullS, field_info->field_name);
|
||||||
if (field)
|
if (field)
|
||||||
{
|
{
|
||||||
field->set_name(field_info->old_name,
|
field->set_name(field_info->old_name,
|
||||||
@ -3264,12 +3266,14 @@ int make_schemata_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
|
|||||||
char tmp[128];
|
char tmp[128];
|
||||||
LEX *lex= thd->lex;
|
LEX *lex= thd->lex;
|
||||||
SELECT_LEX *sel= lex->current_select;
|
SELECT_LEX *sel= lex->current_select;
|
||||||
|
Name_resolution_context *context= &sel->context;
|
||||||
|
|
||||||
if (!sel->item_list.elements)
|
if (!sel->item_list.elements)
|
||||||
{
|
{
|
||||||
ST_FIELD_INFO *field_info= &schema_table->fields_info[1];
|
ST_FIELD_INFO *field_info= &schema_table->fields_info[1];
|
||||||
String buffer(tmp,sizeof(tmp), system_charset_info);
|
String buffer(tmp,sizeof(tmp), system_charset_info);
|
||||||
Item_field *field= new Item_field(NullS, NullS, field_info->field_name);
|
Item_field *field= new Item_field(context,
|
||||||
|
NullS, NullS, field_info->field_name);
|
||||||
if (!field || add_item_to_list(thd, field))
|
if (!field || add_item_to_list(thd, field))
|
||||||
return 1;
|
return 1;
|
||||||
buffer.length(0);
|
buffer.length(0);
|
||||||
@ -3291,6 +3295,7 @@ int make_table_names_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
|
|||||||
char tmp[128];
|
char tmp[128];
|
||||||
String buffer(tmp,sizeof(tmp), thd->charset());
|
String buffer(tmp,sizeof(tmp), thd->charset());
|
||||||
LEX *lex= thd->lex;
|
LEX *lex= thd->lex;
|
||||||
|
Name_resolution_context *context= &lex->select_lex.context;
|
||||||
|
|
||||||
ST_FIELD_INFO *field_info= &schema_table->fields_info[2];
|
ST_FIELD_INFO *field_info= &schema_table->fields_info[2];
|
||||||
buffer.length(0);
|
buffer.length(0);
|
||||||
@ -3302,7 +3307,8 @@ int make_table_names_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
|
|||||||
buffer.append(lex->wild->ptr());
|
buffer.append(lex->wild->ptr());
|
||||||
buffer.append(")");
|
buffer.append(")");
|
||||||
}
|
}
|
||||||
Item_field *field= new Item_field(NullS, NullS, field_info->field_name);
|
Item_field *field= new Item_field(context,
|
||||||
|
NullS, NullS, field_info->field_name);
|
||||||
if (add_item_to_list(thd, field))
|
if (add_item_to_list(thd, field))
|
||||||
return 1;
|
return 1;
|
||||||
field->set_name(buffer.ptr(), buffer.length(), system_charset_info);
|
field->set_name(buffer.ptr(), buffer.length(), system_charset_info);
|
||||||
@ -3310,7 +3316,7 @@ int make_table_names_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
|
|||||||
{
|
{
|
||||||
field->set_name(buffer.ptr(), buffer.length(), system_charset_info);
|
field->set_name(buffer.ptr(), buffer.length(), system_charset_info);
|
||||||
field_info= &schema_table->fields_info[3];
|
field_info= &schema_table->fields_info[3];
|
||||||
field= new Item_field(NullS, NullS, field_info->field_name);
|
field= new Item_field(context, NullS, NullS, field_info->field_name);
|
||||||
if (add_item_to_list(thd, field))
|
if (add_item_to_list(thd, field))
|
||||||
return 1;
|
return 1;
|
||||||
field->set_name(field_info->old_name, strlen(field_info->old_name),
|
field->set_name(field_info->old_name, strlen(field_info->old_name),
|
||||||
@ -3325,6 +3331,8 @@ int make_columns_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
|
|||||||
int fields_arr[]= {3, 14, 13, 6, 15, 5, 16, 17, 18, -1};
|
int fields_arr[]= {3, 14, 13, 6, 15, 5, 16, 17, 18, -1};
|
||||||
int *field_num= fields_arr;
|
int *field_num= fields_arr;
|
||||||
ST_FIELD_INFO *field_info;
|
ST_FIELD_INFO *field_info;
|
||||||
|
Name_resolution_context *context= &thd->lex->select_lex.context;
|
||||||
|
|
||||||
for (; *field_num >= 0; field_num++)
|
for (; *field_num >= 0; field_num++)
|
||||||
{
|
{
|
||||||
field_info= &schema_table->fields_info[*field_num];
|
field_info= &schema_table->fields_info[*field_num];
|
||||||
@ -3332,7 +3340,8 @@ int make_columns_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
|
|||||||
*field_num == 17 ||
|
*field_num == 17 ||
|
||||||
*field_num == 18))
|
*field_num == 18))
|
||||||
continue;
|
continue;
|
||||||
Item_field *field= new Item_field(NullS, NullS, field_info->field_name);
|
Item_field *field= new Item_field(context,
|
||||||
|
NullS, NullS, field_info->field_name);
|
||||||
if (field)
|
if (field)
|
||||||
{
|
{
|
||||||
field->set_name(field_info->old_name,
|
field->set_name(field_info->old_name,
|
||||||
@ -3351,10 +3360,13 @@ int make_character_sets_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
|
|||||||
int fields_arr[]= {0, 2, 1, 3, -1};
|
int fields_arr[]= {0, 2, 1, 3, -1};
|
||||||
int *field_num= fields_arr;
|
int *field_num= fields_arr;
|
||||||
ST_FIELD_INFO *field_info;
|
ST_FIELD_INFO *field_info;
|
||||||
|
Name_resolution_context *context= &thd->lex->select_lex.context;
|
||||||
|
|
||||||
for (; *field_num >= 0; field_num++)
|
for (; *field_num >= 0; field_num++)
|
||||||
{
|
{
|
||||||
field_info= &schema_table->fields_info[*field_num];
|
field_info= &schema_table->fields_info[*field_num];
|
||||||
Item_field *field= new Item_field(NullS, NullS, field_info->field_name);
|
Item_field *field= new Item_field(context,
|
||||||
|
NullS, NullS, field_info->field_name);
|
||||||
if (field)
|
if (field)
|
||||||
{
|
{
|
||||||
field->set_name(field_info->old_name,
|
field->set_name(field_info->old_name,
|
||||||
@ -3373,10 +3385,13 @@ int make_proc_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
|
|||||||
int fields_arr[]= {2, 3, 4, 19, 16, 15, 14, 18, -1};
|
int fields_arr[]= {2, 3, 4, 19, 16, 15, 14, 18, -1};
|
||||||
int *field_num= fields_arr;
|
int *field_num= fields_arr;
|
||||||
ST_FIELD_INFO *field_info;
|
ST_FIELD_INFO *field_info;
|
||||||
|
Name_resolution_context *context= &thd->lex->select_lex.context;
|
||||||
|
|
||||||
for (; *field_num >= 0; field_num++)
|
for (; *field_num >= 0; field_num++)
|
||||||
{
|
{
|
||||||
field_info= &schema_table->fields_info[*field_num];
|
field_info= &schema_table->fields_info[*field_num];
|
||||||
Item_field *field= new Item_field(NullS, NullS, field_info->field_name);
|
Item_field *field= new Item_field(context,
|
||||||
|
NullS, NullS, field_info->field_name);
|
||||||
if (field)
|
if (field)
|
||||||
{
|
{
|
||||||
field->set_name(field_info->old_name,
|
field->set_name(field_info->old_name,
|
||||||
@ -3442,12 +3457,11 @@ int mysql_schema_table(THD *thd, LEX *lex, TABLE_LIST *table_list)
|
|||||||
|
|
||||||
if (table_list->field_translation)
|
if (table_list->field_translation)
|
||||||
{
|
{
|
||||||
Field_translator *end= table_list->field_translation +
|
Field_translator *end= table_list->field_translation_end;
|
||||||
sel->item_list.elements;
|
|
||||||
for (transl= table_list->field_translation; transl < end; transl++)
|
for (transl= table_list->field_translation; transl < end; transl++)
|
||||||
{
|
{
|
||||||
if (!transl->item->fixed &&
|
if (!transl->item->fixed &&
|
||||||
transl->item->fix_fields(thd, table_list, &transl->item))
|
transl->item->fix_fields(thd, &transl->item))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
@ -3464,11 +3478,12 @@ int mysql_schema_table(THD *thd, LEX *lex, TABLE_LIST *table_list)
|
|||||||
{
|
{
|
||||||
char *name= item->name;
|
char *name= item->name;
|
||||||
transl[i].item= item;
|
transl[i].item= item;
|
||||||
if (!item->fixed && item->fix_fields(thd, table_list, &transl[i].item))
|
if (!item->fixed && item->fix_fields(thd, &transl[i].item))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
transl[i++].name= name;
|
transl[i++].name= name;
|
||||||
}
|
}
|
||||||
table_list->field_translation= transl;
|
table_list->field_translation= transl;
|
||||||
|
table_list->field_translation_end= transl + sel->item_list.elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
|
@ -201,7 +201,7 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables)
|
|||||||
{
|
{
|
||||||
trg_field->setup_field(thd, table);
|
trg_field->setup_field(thd, table);
|
||||||
if (!trg_field->fixed &&
|
if (!trg_field->fixed &&
|
||||||
trg_field->fix_fields(thd, (TABLE_LIST *)0, (Item **)0))
|
trg_field->fix_fields(thd, (Item **)0))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ class udf_handler :public Sql_alloc
|
|||||||
Item_result result_type () const
|
Item_result result_type () const
|
||||||
{ return u_d ? u_d->returns : STRING_RESULT;}
|
{ return u_d ? u_d->returns : STRING_RESULT;}
|
||||||
bool get_arguments();
|
bool get_arguments();
|
||||||
bool fix_fields(THD *thd,struct st_table_list *tlist,Item_result_field *item,
|
bool fix_fields(THD *thd, Item_result_field *item,
|
||||||
uint arg_count, Item **args);
|
uint arg_count, Item **args);
|
||||||
void cleanup();
|
void cleanup();
|
||||||
double val(my_bool *null_value)
|
double val(my_bool *null_value)
|
||||||
|
@ -124,6 +124,13 @@ st_select_lex_unit::init_prepare_fake_select_lex(THD *thd)
|
|||||||
fake_select_lex->table_list.link_in_list((byte *)&result_table_list,
|
fake_select_lex->table_list.link_in_list((byte *)&result_table_list,
|
||||||
(byte **)
|
(byte **)
|
||||||
&result_table_list.next_local);
|
&result_table_list.next_local);
|
||||||
|
for (ORDER *order= (ORDER *)global_parameters->order_list.first;
|
||||||
|
order;
|
||||||
|
order=order->next)
|
||||||
|
{
|
||||||
|
(*order->item)->walk(&Item::change_context_processor,
|
||||||
|
(byte *) &fake_select_lex->context);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -187,6 +194,8 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
|
|||||||
else
|
else
|
||||||
tmp_result= sel_result;
|
tmp_result= sel_result;
|
||||||
|
|
||||||
|
sl->context.resolve_in_select_list= TRUE;
|
||||||
|
|
||||||
for (;sl; sl= sl->next_select())
|
for (;sl; sl= sl->next_select())
|
||||||
{
|
{
|
||||||
bool can_skip_order_by;
|
bool can_skip_order_by;
|
||||||
|
@ -67,6 +67,8 @@ static bool check_fields(THD *thd, List<Item> &items)
|
|||||||
List_iterator<Item> it(items);
|
List_iterator<Item> it(items);
|
||||||
Item *item;
|
Item *item;
|
||||||
Item_field *field;
|
Item_field *field;
|
||||||
|
Name_resolution_context *context= &thd->lex->select_lex.context;
|
||||||
|
|
||||||
while ((item= it++))
|
while ((item= it++))
|
||||||
{
|
{
|
||||||
if (!(field= item->filed_for_view_update()))
|
if (!(field= item->filed_for_view_update()))
|
||||||
@ -185,14 +187,8 @@ int mysql_update(THD *thd,
|
|||||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||||
table_list->grant.want_privilege= table->grant.want_privilege= want_privilege;
|
table_list->grant.want_privilege= table->grant.want_privilege= want_privilege;
|
||||||
#endif
|
#endif
|
||||||
{
|
if (setup_fields_with_no_wrap(thd, 0, fields, 1, 0, 0))
|
||||||
bool res;
|
|
||||||
select_lex->no_wrap_view_item= 1;
|
|
||||||
res= setup_fields(thd, 0, table_list, fields, 1, 0, 0);
|
|
||||||
select_lex->no_wrap_view_item= 0;
|
|
||||||
if (res)
|
|
||||||
DBUG_RETURN(1); /* purecov: inspected */
|
DBUG_RETURN(1); /* purecov: inspected */
|
||||||
}
|
|
||||||
if (table_list->view && check_fields(thd, fields))
|
if (table_list->view && check_fields(thd, fields))
|
||||||
{
|
{
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
@ -216,7 +212,7 @@ int mysql_update(THD *thd,
|
|||||||
table_list->grant.want_privilege= table->grant.want_privilege=
|
table_list->grant.want_privilege= table->grant.want_privilege=
|
||||||
(SELECT_ACL & ~table->grant.privilege);
|
(SELECT_ACL & ~table->grant.privilege);
|
||||||
#endif
|
#endif
|
||||||
if (setup_fields(thd, 0, table_list, values, 1, 0, 0))
|
if (setup_fields(thd, 0, values, 1, 0, 0))
|
||||||
{
|
{
|
||||||
free_underlaid_joins(thd, select_lex);
|
free_underlaid_joins(thd, select_lex);
|
||||||
DBUG_RETURN(1); /* purecov: inspected */
|
DBUG_RETURN(1); /* purecov: inspected */
|
||||||
@ -557,7 +553,9 @@ bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
|
|||||||
tables.table= table;
|
tables.table= table;
|
||||||
tables.alias= table_list->alias;
|
tables.alias= table_list->alias;
|
||||||
|
|
||||||
if (setup_tables(thd, table_list, conds, &select_lex->leaf_tables, FALSE) ||
|
if (setup_tables(thd, &select_lex->context,
|
||||||
|
table_list, conds, &select_lex->leaf_tables,
|
||||||
|
FALSE) ||
|
||||||
setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
|
setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
|
||||||
select_lex->setup_ref_array(thd, order_num) ||
|
select_lex->setup_ref_array(thd, order_num) ||
|
||||||
setup_order(thd, select_lex->ref_pointer_array,
|
setup_order(thd, select_lex->ref_pointer_array,
|
||||||
@ -617,7 +615,6 @@ bool mysql_multi_update_prepare(THD *thd)
|
|||||||
TABLE_LIST *tl, *leaves;
|
TABLE_LIST *tl, *leaves;
|
||||||
List<Item> *fields= &lex->select_lex.item_list;
|
List<Item> *fields= &lex->select_lex.item_list;
|
||||||
table_map tables_for_update;
|
table_map tables_for_update;
|
||||||
int res;
|
|
||||||
bool update_view= 0;
|
bool update_view= 0;
|
||||||
/*
|
/*
|
||||||
if this multi-update was converted from usual update, here is table
|
if this multi-update was converted from usual update, here is table
|
||||||
@ -642,15 +639,12 @@ bool mysql_multi_update_prepare(THD *thd)
|
|||||||
call in setup_tables()).
|
call in setup_tables()).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (setup_tables(thd, table_list, &lex->select_lex.where,
|
if (setup_tables(thd, &lex->select_lex.context,
|
||||||
|
table_list, &lex->select_lex.where,
|
||||||
&lex->select_lex.leaf_tables, FALSE))
|
&lex->select_lex.leaf_tables, FALSE))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
leaves= lex->select_lex.leaf_tables;
|
|
||||||
|
|
||||||
if ((lex->select_lex.no_wrap_view_item= 1,
|
if (setup_fields_with_no_wrap(thd, 0, *fields, 1, 0, 0))
|
||||||
res= setup_fields(thd, 0, table_list, *fields, 1, 0, 0),
|
|
||||||
lex->select_lex.no_wrap_view_item= 0,
|
|
||||||
res))
|
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
for (tl= table_list; tl ; tl= tl->next_local)
|
for (tl= table_list; tl ; tl= tl->next_local)
|
||||||
@ -672,6 +666,7 @@ bool mysql_multi_update_prepare(THD *thd)
|
|||||||
/*
|
/*
|
||||||
Setup timestamp handling and locking mode
|
Setup timestamp handling and locking mode
|
||||||
*/
|
*/
|
||||||
|
leaves= lex->select_lex.leaf_tables;
|
||||||
for (tl= leaves; tl; tl= tl->next_leaf)
|
for (tl= leaves; tl; tl= tl->next_leaf)
|
||||||
{
|
{
|
||||||
TABLE *table= tl->table;
|
TABLE *table= tl->table;
|
||||||
@ -762,12 +757,10 @@ bool mysql_multi_update_prepare(THD *thd)
|
|||||||
for (TABLE_LIST *tbl= table_list; tbl; tbl= tbl->next_global)
|
for (TABLE_LIST *tbl= table_list; tbl; tbl= tbl->next_global)
|
||||||
tbl->cleanup_items();
|
tbl->cleanup_items();
|
||||||
|
|
||||||
if (setup_tables(thd, table_list, &lex->select_lex.where,
|
if (setup_tables(thd, &lex->select_lex.context,
|
||||||
|
table_list, &lex->select_lex.where,
|
||||||
&lex->select_lex.leaf_tables, FALSE) ||
|
&lex->select_lex.leaf_tables, FALSE) ||
|
||||||
(lex->select_lex.no_wrap_view_item= 1,
|
setup_fields_with_no_wrap(thd, 0, *fields, 1, 0, 0))
|
||||||
res= setup_fields(thd, 0, table_list, *fields, 1, 0, 0),
|
|
||||||
lex->select_lex.no_wrap_view_item= 0,
|
|
||||||
res))
|
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -897,7 +890,7 @@ int multi_update::prepare(List<Item> ¬_used_values,
|
|||||||
reference tables
|
reference tables
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (setup_fields(thd, 0, all_tables, *values, 1, 0, 0))
|
if (setup_fields(thd, 0, *values, 1, 0, 0))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -828,10 +828,23 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
|
|||||||
table->effective_algorithm= VIEW_ALGORITHM_MERGE;
|
table->effective_algorithm= VIEW_ALGORITHM_MERGE;
|
||||||
DBUG_PRINT("info", ("algorithm: MERGE"));
|
DBUG_PRINT("info", ("algorithm: MERGE"));
|
||||||
table->updatable= (table->updatable_view != 0);
|
table->updatable= (table->updatable_view != 0);
|
||||||
table->effective_with_check= (uint8)table->with_check;
|
table->effective_with_check=
|
||||||
|
old_lex->get_effective_with_check(table);
|
||||||
table->ancestor= view_tables;
|
|
||||||
|
|
||||||
|
/* prepare view context */
|
||||||
|
lex->select_lex.context.resolve_in_table_list_only(table->ancestor=
|
||||||
|
view_tables);
|
||||||
|
lex->select_lex.context.outer_context= 0;
|
||||||
|
lex->select_lex.context.select_lex= table->select_lex;
|
||||||
|
/* do not check privileges & hide errors for view underlyings */
|
||||||
|
for (SELECT_LEX *sl= lex->all_selects_list;
|
||||||
|
sl;
|
||||||
|
sl= sl->next_select_in_list())
|
||||||
|
{
|
||||||
|
sl->context.check_privileges= FALSE;
|
||||||
|
sl->context.error_processor= &view_error_processor;
|
||||||
|
sl->context.error_processor_data= (void *)table;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
Tables of the main select of the view should be marked as belonging
|
Tables of the main select of the view should be marked as belonging
|
||||||
to the same select as original view (again we can use LEX::select_lex
|
to the same select as original view (again we can use LEX::select_lex
|
||||||
@ -866,7 +879,6 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
|
|||||||
table->where= view_select->where;
|
table->where= view_select->where;
|
||||||
/*
|
/*
|
||||||
Add subqueries units to SELECT into which we merging current view.
|
Add subqueries units to SELECT into which we merging current view.
|
||||||
|
|
||||||
unit(->next)* chain starts with subqueries that are used by this
|
unit(->next)* chain starts with subqueries that are used by this
|
||||||
view and continues with subqueries that are used by other views.
|
view and continues with subqueries that are used by other views.
|
||||||
We must not add any subquery twice (otherwise we'll form a loop),
|
We must not add any subquery twice (otherwise we'll form a loop),
|
||||||
@ -1058,9 +1070,9 @@ frm_type_enum mysql_frm_type(char *path)
|
|||||||
bool check_key_in_view(THD *thd, TABLE_LIST *view)
|
bool check_key_in_view(THD *thd, TABLE_LIST *view)
|
||||||
{
|
{
|
||||||
TABLE *table;
|
TABLE *table;
|
||||||
Field_translator *trans;
|
Field_translator *trans, *end_of_trans;
|
||||||
KEY *key_info, *key_info_end;
|
KEY *key_info, *key_info_end;
|
||||||
uint i, elements_in_view;
|
uint i;
|
||||||
DBUG_ENTER("check_key_in_view");
|
DBUG_ENTER("check_key_in_view");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1077,9 +1089,24 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view)
|
|||||||
trans= view->field_translation;
|
trans= view->field_translation;
|
||||||
key_info_end= (key_info= table->key_info)+ table->s->keys;
|
key_info_end= (key_info= table->key_info)+ table->s->keys;
|
||||||
|
|
||||||
elements_in_view= view->view->select_lex.item_list.elements;
|
end_of_trans= view->field_translation_end;
|
||||||
DBUG_ASSERT(table != 0 && view->field_translation != 0);
|
DBUG_ASSERT(table != 0 && view->field_translation != 0);
|
||||||
|
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
We should be sure that all fields are ready to get keys from them, but
|
||||||
|
this operation should not have influence on Field::query_id, to avoid
|
||||||
|
marking as used fields which are not used
|
||||||
|
*/
|
||||||
|
bool save_set_query_id= thd->set_query_id;
|
||||||
|
thd->set_query_id= 0;
|
||||||
|
for (Field_translator *fld= trans; fld < end_of_trans; fld++)
|
||||||
|
{
|
||||||
|
if (!fld->item->fixed && fld->item->fix_fields(thd, &fld->item))
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
thd->set_query_id= save_set_query_id;
|
||||||
|
}
|
||||||
/* Loop over all keys to see if a unique-not-null key is used */
|
/* Loop over all keys to see if a unique-not-null key is used */
|
||||||
for (;key_info != key_info_end ; key_info++)
|
for (;key_info != key_info_end ; key_info++)
|
||||||
{
|
{
|
||||||
@ -1091,15 +1118,15 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view)
|
|||||||
/* check that all key parts are used */
|
/* check that all key parts are used */
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
uint k;
|
Field_translator *k;
|
||||||
for (k= 0; k < elements_in_view; k++)
|
for (k= trans; k < end_of_trans; k++)
|
||||||
{
|
{
|
||||||
Item_field *field;
|
Item_field *field;
|
||||||
if ((field= trans[k].item->filed_for_view_update()) &&
|
if ((field= k->item->filed_for_view_update()) &&
|
||||||
field->field == key_part->field)
|
field->field == key_part->field)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (k == elements_in_view)
|
if (k == end_of_trans)
|
||||||
break; // Key is not possible
|
break; // Key is not possible
|
||||||
if (++key_part == key_part_end)
|
if (++key_part == key_part_end)
|
||||||
DBUG_RETURN(FALSE); // Found usable key
|
DBUG_RETURN(FALSE); // Found usable key
|
||||||
@ -1111,19 +1138,20 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view)
|
|||||||
/* check all fields presence */
|
/* check all fields presence */
|
||||||
{
|
{
|
||||||
Field **field_ptr;
|
Field **field_ptr;
|
||||||
|
Field_translator *fld;
|
||||||
for (field_ptr= table->field; *field_ptr; field_ptr++)
|
for (field_ptr= table->field; *field_ptr; field_ptr++)
|
||||||
{
|
{
|
||||||
for (i= 0; i < elements_in_view; i++)
|
for (fld= trans; fld < end_of_trans; fld++)
|
||||||
{
|
{
|
||||||
Item_field *field;
|
Item_field *field;
|
||||||
if ((field= trans[i].item->filed_for_view_update()) &&
|
if ((field= fld->item->filed_for_view_update()) &&
|
||||||
field->field == *field_ptr)
|
field->field == *field_ptr)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (i == elements_in_view) // If field didn't exists
|
if (fld == end_of_trans) // If field didn't exists
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Keys or all fields of underlying tables are not foud => we have
|
Keys or all fields of underlying tables are not found => we have
|
||||||
to check variable updatable_views_with_limit to decide should we
|
to check variable updatable_views_with_limit to decide should we
|
||||||
issue an error or just a warning
|
issue an error or just a warning
|
||||||
*/
|
*/
|
||||||
@ -1148,6 +1176,7 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view)
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
insert_view_fields()
|
insert_view_fields()
|
||||||
|
thd thread handler
|
||||||
list list for insertion
|
list list for insertion
|
||||||
view view for processing
|
view view for processing
|
||||||
|
|
||||||
@ -1156,19 +1185,22 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view)
|
|||||||
TRUE error (is not sent to cliet)
|
TRUE error (is not sent to cliet)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool insert_view_fields(List<Item> *list, TABLE_LIST *view)
|
bool insert_view_fields(THD *thd, List<Item> *list, TABLE_LIST *view)
|
||||||
{
|
{
|
||||||
uint elements_in_view= view->view->select_lex.item_list.elements;
|
Field_translator *trans_end;
|
||||||
Field_translator *trans;
|
Field_translator *trans;
|
||||||
DBUG_ENTER("insert_view_fields");
|
DBUG_ENTER("insert_view_fields");
|
||||||
|
|
||||||
if (!(trans= view->field_translation))
|
if (!(trans= view->field_translation))
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
|
trans_end= view->field_translation_end;
|
||||||
|
|
||||||
for (uint i= 0; i < elements_in_view; i++)
|
for (Field_translator *entry= trans; entry < trans_end; entry++)
|
||||||
{
|
{
|
||||||
Item_field *fld;
|
Item_field *fld;
|
||||||
if ((fld= trans[i].item->filed_for_view_update()))
|
if (!entry->item->fixed && entry->item->fix_fields(thd, &entry->item))
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
if ((fld= entry->item->filed_for_view_update()))
|
||||||
list->push_back(fld);
|
list->push_back(fld);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -25,7 +25,7 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *view, enum_drop_mode drop_mode);
|
|||||||
|
|
||||||
bool check_key_in_view(THD *thd, TABLE_LIST * view);
|
bool check_key_in_view(THD *thd, TABLE_LIST * view);
|
||||||
|
|
||||||
bool insert_view_fields(List<Item> *list, TABLE_LIST *view);
|
bool insert_view_fields(THD *thd, List<Item> *list, TABLE_LIST *view);
|
||||||
|
|
||||||
frm_type_enum mysql_frm_type(char *path);
|
frm_type_enum mysql_frm_type(char *path);
|
||||||
|
|
||||||
|
@ -1259,7 +1259,6 @@ create:
|
|||||||
THD *thd= YYTHD;
|
THD *thd= YYTHD;
|
||||||
LEX *lex= thd->lex;
|
LEX *lex= thd->lex;
|
||||||
lex->sql_command= SQLCOM_CREATE_VIEW;
|
lex->sql_command= SQLCOM_CREATE_VIEW;
|
||||||
lex->select_lex.resolve_mode= SELECT_LEX::SELECT_MODE;
|
|
||||||
/* first table in list is target VIEW name */
|
/* first table in list is target VIEW name */
|
||||||
if (!lex->select_lex.add_table_to_list(thd, $5, NULL, 0))
|
if (!lex->select_lex.add_table_to_list(thd, $5, NULL, 0))
|
||||||
YYABORT;
|
YYABORT;
|
||||||
@ -3383,7 +3382,6 @@ alter:
|
|||||||
LEX *lex= thd->lex;
|
LEX *lex= thd->lex;
|
||||||
lex->sql_command= SQLCOM_CREATE_VIEW;
|
lex->sql_command= SQLCOM_CREATE_VIEW;
|
||||||
lex->create_view_mode= VIEW_ALTER;
|
lex->create_view_mode= VIEW_ALTER;
|
||||||
lex->select_lex.resolve_mode= SELECT_LEX::SELECT_MODE;
|
|
||||||
/* first table in list is target VIEW name */
|
/* first table in list is target VIEW name */
|
||||||
lex->select_lex.add_table_to_list(thd, $4, NULL, 0);
|
lex->select_lex.add_table_to_list(thd, $4, NULL, 0);
|
||||||
}
|
}
|
||||||
@ -3941,7 +3939,6 @@ select:
|
|||||||
{
|
{
|
||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
lex->sql_command= SQLCOM_SELECT;
|
lex->sql_command= SQLCOM_SELECT;
|
||||||
lex->select_lex.resolve_mode= SELECT_LEX::SELECT_MODE;
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -4095,7 +4092,10 @@ select_item_list:
|
|||||||
| '*'
|
| '*'
|
||||||
{
|
{
|
||||||
THD *thd= YYTHD;
|
THD *thd= YYTHD;
|
||||||
if (add_item_to_list(thd, new Item_field(NULL, NULL, "*")))
|
if (add_item_to_list(thd,
|
||||||
|
new Item_field(&thd->lex->current_select->
|
||||||
|
context,
|
||||||
|
NULL, NULL, "*")))
|
||||||
YYABORT;
|
YYABORT;
|
||||||
(thd->lex->current_select->with_wild)++;
|
(thd->lex->current_select->with_wild)++;
|
||||||
};
|
};
|
||||||
@ -4393,10 +4393,10 @@ simple_expr:
|
|||||||
my_error(ER_WRONG_COLUMN_NAME, MYF(0), name->str);
|
my_error(ER_WRONG_COLUMN_NAME, MYF(0), name->str);
|
||||||
YYABORT;
|
YYABORT;
|
||||||
}
|
}
|
||||||
$$= new Item_default_value($3);
|
$$= new Item_default_value(&Select->context, $3);
|
||||||
}
|
}
|
||||||
| VALUES '(' simple_ident ')'
|
| VALUES '(' simple_ident ')'
|
||||||
{ $$= new Item_insert_value($3); }
|
{ $$= new Item_insert_value(&Select->context, $3); }
|
||||||
| FUNC_ARG0 '(' ')'
|
| FUNC_ARG0 '(' ')'
|
||||||
{
|
{
|
||||||
if (!$1.symbol->create_func)
|
if (!$1.symbol->create_func)
|
||||||
@ -4687,15 +4687,16 @@ simple_expr:
|
|||||||
name->init_qname(YYTHD);
|
name->init_qname(YYTHD);
|
||||||
sp_add_to_hash(&lex->spfuns, name);
|
sp_add_to_hash(&lex->spfuns, name);
|
||||||
if ($5)
|
if ($5)
|
||||||
$$= new Item_func_sp(name, *$5);
|
$$= new Item_func_sp(&lex->current_select->context, name, *$5);
|
||||||
else
|
else
|
||||||
$$= new Item_func_sp(name);
|
$$= new Item_func_sp(&lex->current_select->context, name);
|
||||||
lex->safe_to_cache_query=0;
|
lex->safe_to_cache_query=0;
|
||||||
}
|
}
|
||||||
| IDENT_sys '(' udf_expr_list ')'
|
| IDENT_sys '(' udf_expr_list ')'
|
||||||
{
|
{
|
||||||
#ifdef HAVE_DLOPEN
|
#ifdef HAVE_DLOPEN
|
||||||
udf_func *udf;
|
udf_func *udf;
|
||||||
|
SELECT_LEX *sel= Select;
|
||||||
|
|
||||||
if (using_udf_functions && (udf=find_udf($1.str, $1.length)))
|
if (using_udf_functions && (udf=find_udf($1.str, $1.length)))
|
||||||
{
|
{
|
||||||
@ -4776,9 +4777,9 @@ simple_expr:
|
|||||||
|
|
||||||
sp_add_to_hash(&lex->spfuns, name);
|
sp_add_to_hash(&lex->spfuns, name);
|
||||||
if ($3)
|
if ($3)
|
||||||
$$= new Item_func_sp(name, *$3);
|
$$= new Item_func_sp(&lex->current_select->context, name, *$3);
|
||||||
else
|
else
|
||||||
$$= new Item_func_sp(name);
|
$$= new Item_func_sp(&lex->current_select->context, name);
|
||||||
lex->safe_to_cache_query=0;
|
lex->safe_to_cache_query=0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4980,8 +4981,10 @@ sum_expr:
|
|||||||
opt_gconcat_separator
|
opt_gconcat_separator
|
||||||
')'
|
')'
|
||||||
{
|
{
|
||||||
Select->in_sum_expr--;
|
SELECT_LEX *sel= Select;
|
||||||
$$=new Item_func_group_concat($3,$5,Select->gorder_list,$7);
|
sel->in_sum_expr--;
|
||||||
|
$$=new Item_func_group_concat(&sel->context, $3, $5,
|
||||||
|
sel->gorder_list, $7);
|
||||||
$5->empty();
|
$5->empty();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -5400,16 +5403,30 @@ using_list:
|
|||||||
ident
|
ident
|
||||||
{
|
{
|
||||||
SELECT_LEX *sel= Select;
|
SELECT_LEX *sel= Select;
|
||||||
if (!($$= new Item_func_eq(new Item_field(sel->db1, sel->table1,
|
if (!($$= new Item_func_eq(new Item_field(&sel->context,
|
||||||
|
sel->db1, sel->table1,
|
||||||
$1.str),
|
$1.str),
|
||||||
new Item_field(sel->db2, sel->table2,
|
new Item_field(&sel->context,
|
||||||
|
sel->db2, sel->table2,
|
||||||
$1.str))))
|
$1.str))))
|
||||||
YYABORT;
|
YYABORT;
|
||||||
}
|
}
|
||||||
| using_list ',' ident
|
| using_list ',' ident
|
||||||
{
|
{
|
||||||
SELECT_LEX *sel= Select;
|
SELECT_LEX *sel= Select;
|
||||||
if (!($$= new Item_cond_and(new Item_func_eq(new Item_field(sel->db1,sel->table1,$3.str), new Item_field(sel->db2,sel->table2,$3.str)), $1)))
|
if (!($$=
|
||||||
|
new Item_cond_and(new
|
||||||
|
Item_func_eq(new
|
||||||
|
Item_field(&sel->context,
|
||||||
|
sel->db1,
|
||||||
|
sel->table1,
|
||||||
|
$3.str),
|
||||||
|
new
|
||||||
|
Item_field(&sel->context,
|
||||||
|
sel->db2,
|
||||||
|
sel->table2,
|
||||||
|
$3.str)),
|
||||||
|
$1)))
|
||||||
YYABORT;
|
YYABORT;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -5675,7 +5692,10 @@ procedure_clause:
|
|||||||
lex->proc_list.elements=0;
|
lex->proc_list.elements=0;
|
||||||
lex->proc_list.first=0;
|
lex->proc_list.first=0;
|
||||||
lex->proc_list.next= (byte**) &lex->proc_list.first;
|
lex->proc_list.next= (byte**) &lex->proc_list.first;
|
||||||
if (add_proc_to_list(lex->thd, new Item_field(NULL,NULL,$2.str)))
|
if (add_proc_to_list(lex->thd, new Item_field(&lex->
|
||||||
|
current_select->
|
||||||
|
context,
|
||||||
|
NULL,NULL,$2.str)))
|
||||||
YYABORT;
|
YYABORT;
|
||||||
Lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
|
Lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
|
||||||
}
|
}
|
||||||
@ -5922,7 +5942,6 @@ insert:
|
|||||||
mysql_init_select(lex);
|
mysql_init_select(lex);
|
||||||
/* for subselects */
|
/* for subselects */
|
||||||
lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ;
|
lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ;
|
||||||
lex->select_lex.resolve_mode= SELECT_LEX::INSERT_MODE;
|
|
||||||
} insert_lock_option
|
} insert_lock_option
|
||||||
opt_ignore insert2
|
opt_ignore insert2
|
||||||
{
|
{
|
||||||
@ -5940,7 +5959,6 @@ replace:
|
|||||||
lex->sql_command = SQLCOM_REPLACE;
|
lex->sql_command = SQLCOM_REPLACE;
|
||||||
lex->duplicates= DUP_REPLACE;
|
lex->duplicates= DUP_REPLACE;
|
||||||
mysql_init_select(lex);
|
mysql_init_select(lex);
|
||||||
lex->select_lex.resolve_mode= SELECT_LEX::INSERT_MODE;
|
|
||||||
}
|
}
|
||||||
replace_lock_option insert2
|
replace_lock_option insert2
|
||||||
{
|
{
|
||||||
@ -6058,7 +6076,7 @@ values:
|
|||||||
|
|
||||||
expr_or_default:
|
expr_or_default:
|
||||||
expr { $$= $1;}
|
expr { $$= $1;}
|
||||||
| DEFAULT {$$= new Item_default_value(); }
|
| DEFAULT {$$= new Item_default_value(&Select->context); }
|
||||||
;
|
;
|
||||||
|
|
||||||
opt_insert_update:
|
opt_insert_update:
|
||||||
@ -7027,15 +7045,17 @@ insert_ident:
|
|||||||
table_wild:
|
table_wild:
|
||||||
ident '.' '*'
|
ident '.' '*'
|
||||||
{
|
{
|
||||||
$$ = new Item_field(NullS,$1.str,"*");
|
SELECT_LEX *sel= Select;
|
||||||
Lex->current_select->with_wild++;
|
$$ = new Item_field(&sel->context, NullS, $1.str, "*");
|
||||||
|
sel->with_wild++;
|
||||||
}
|
}
|
||||||
| ident '.' ident '.' '*'
|
| ident '.' ident '.' '*'
|
||||||
{
|
{
|
||||||
$$ = new Item_field((YYTHD->client_capabilities &
|
SELECT_LEX *sel= Select;
|
||||||
|
$$ = new Item_field(&sel->context, (YYTHD->client_capabilities &
|
||||||
CLIENT_NO_SCHEMA ? NullS : $1.str),
|
CLIENT_NO_SCHEMA ? NullS : $1.str),
|
||||||
$3.str,"*");
|
$3.str,"*");
|
||||||
Lex->current_select->with_wild++;
|
sel->with_wild++;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -7060,8 +7080,8 @@ simple_ident:
|
|||||||
SELECT_LEX *sel=Select;
|
SELECT_LEX *sel=Select;
|
||||||
$$= (sel->parsing_place != IN_HAVING ||
|
$$= (sel->parsing_place != IN_HAVING ||
|
||||||
sel->get_in_sum_expr() > 0) ?
|
sel->get_in_sum_expr() > 0) ?
|
||||||
(Item*) new Item_field(NullS,NullS,$1.str) :
|
(Item*) new Item_field(&sel->context, NullS, NullS, $1.str) :
|
||||||
(Item*) new Item_ref(NullS,NullS,$1.str);
|
(Item*) new Item_ref(&sel->context, NullS, NullS, $1.str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| simple_ident_q { $$= $1; }
|
| simple_ident_q { $$= $1; }
|
||||||
@ -7073,8 +7093,8 @@ simple_ident_nospvar:
|
|||||||
SELECT_LEX *sel=Select;
|
SELECT_LEX *sel=Select;
|
||||||
$$= (sel->parsing_place != IN_HAVING ||
|
$$= (sel->parsing_place != IN_HAVING ||
|
||||||
sel->get_in_sum_expr() > 0) ?
|
sel->get_in_sum_expr() > 0) ?
|
||||||
(Item*) new Item_field(NullS,NullS,$1.str) :
|
(Item*) new Item_field(&sel->context, NullS, NullS, $1.str) :
|
||||||
(Item*) new Item_ref(NullS,NullS,$1.str);
|
(Item*) new Item_ref(&sel->context, NullS, NullS, $1.str);
|
||||||
}
|
}
|
||||||
| simple_ident_q { $$= $1; }
|
| simple_ident_q { $$= $1; }
|
||||||
;
|
;
|
||||||
@ -7111,7 +7131,8 @@ simple_ident_q:
|
|||||||
YYABORT;
|
YYABORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(trg_fld= new Item_trigger_field(new_row ?
|
if (!(trg_fld= new Item_trigger_field(&lex->current_select->context,
|
||||||
|
new_row ?
|
||||||
Item_trigger_field::NEW_ROW:
|
Item_trigger_field::NEW_ROW:
|
||||||
Item_trigger_field::OLD_ROW,
|
Item_trigger_field::OLD_ROW,
|
||||||
$3.str)))
|
$3.str)))
|
||||||
@ -7136,8 +7157,8 @@ simple_ident_q:
|
|||||||
}
|
}
|
||||||
$$= (sel->parsing_place != IN_HAVING ||
|
$$= (sel->parsing_place != IN_HAVING ||
|
||||||
sel->get_in_sum_expr() > 0) ?
|
sel->get_in_sum_expr() > 0) ?
|
||||||
(Item*) new Item_field(NullS,$1.str,$3.str) :
|
(Item*) new Item_field(&sel->context, NullS, $1.str, $3.str) :
|
||||||
(Item*) new Item_ref(NullS,$1.str,$3.str);
|
(Item*) new Item_ref(&sel->context, NullS, $1.str, $3.str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| '.' ident '.' ident
|
| '.' ident '.' ident
|
||||||
@ -7152,8 +7173,8 @@ simple_ident_q:
|
|||||||
}
|
}
|
||||||
$$= (sel->parsing_place != IN_HAVING ||
|
$$= (sel->parsing_place != IN_HAVING ||
|
||||||
sel->get_in_sum_expr() > 0) ?
|
sel->get_in_sum_expr() > 0) ?
|
||||||
(Item*) new Item_field(NullS,$2.str,$4.str) :
|
(Item*) new Item_field(&sel->context, NullS, $2.str, $4.str) :
|
||||||
(Item*) new Item_ref(NullS, $2.str, $4.str);
|
(Item*) new Item_ref(&sel->context, NullS, $2.str, $4.str);
|
||||||
}
|
}
|
||||||
| ident '.' ident '.' ident
|
| ident '.' ident '.' ident
|
||||||
{
|
{
|
||||||
@ -7167,10 +7188,12 @@ simple_ident_q:
|
|||||||
}
|
}
|
||||||
$$= (sel->parsing_place != IN_HAVING ||
|
$$= (sel->parsing_place != IN_HAVING ||
|
||||||
sel->get_in_sum_expr() > 0) ?
|
sel->get_in_sum_expr() > 0) ?
|
||||||
(Item*) new Item_field((YYTHD->client_capabilities &
|
(Item*) new Item_field(&sel->context,
|
||||||
|
(YYTHD->client_capabilities &
|
||||||
CLIENT_NO_SCHEMA ? NullS : $1.str),
|
CLIENT_NO_SCHEMA ? NullS : $1.str),
|
||||||
$3.str, $5.str) :
|
$3.str, $5.str) :
|
||||||
(Item*) new Item_ref((YYTHD->client_capabilities &
|
(Item*) new Item_ref(&sel->context,
|
||||||
|
(YYTHD->client_capabilities &
|
||||||
CLIENT_NO_SCHEMA ? NullS : $1.str),
|
CLIENT_NO_SCHEMA ? NullS : $1.str),
|
||||||
$3.str, $5.str);
|
$3.str, $5.str);
|
||||||
};
|
};
|
||||||
@ -7720,9 +7743,11 @@ sys_option_value:
|
|||||||
it= new Item_null();
|
it= new Item_null();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(trg_fld= new Item_trigger_field(Item_trigger_field::NEW_ROW,
|
if (!(trg_fld= new Item_trigger_field(&lex->current_select->context,
|
||||||
|
Item_trigger_field::NEW_ROW,
|
||||||
$2.base_name.str)) ||
|
$2.base_name.str)) ||
|
||||||
!(i= new sp_instr_set_trigger_field(
|
!(i= new sp_instr_set_trigger_field(
|
||||||
|
&lex->current_select->context,
|
||||||
lex->sphead->instructions(), lex->spcont,
|
lex->sphead->instructions(), lex->spcont,
|
||||||
trg_fld, it)))
|
trg_fld, it)))
|
||||||
YYABORT;
|
YYABORT;
|
||||||
|
440
sql/table.cc
440
sql/table.cc
@ -594,6 +594,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
|
|||||||
goto err; /* purecov: inspected */
|
goto err; /* purecov: inspected */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reg_field->field_index= i;
|
||||||
reg_field->comment=comment;
|
reg_field->comment=comment;
|
||||||
if (field_type == FIELD_TYPE_BIT && !f_bit_as_char(pack_flag))
|
if (field_type == FIELD_TYPE_BIT && !f_bit_as_char(pack_flag))
|
||||||
{
|
{
|
||||||
@ -1713,8 +1714,6 @@ void st_table_list::set_ancestor()
|
|||||||
}
|
}
|
||||||
if (tbl->multitable_view)
|
if (tbl->multitable_view)
|
||||||
multitable_view= TRUE;
|
multitable_view= TRUE;
|
||||||
if (tbl->table)
|
|
||||||
tbl->table->grant= grant;
|
|
||||||
} while ((tbl= tbl->next_local));
|
} while ((tbl= tbl->next_local));
|
||||||
|
|
||||||
if (!multitable_view)
|
if (!multitable_view)
|
||||||
@ -1726,69 +1725,19 @@ void st_table_list::set_ancestor()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Save old want_privilege and clear want_privilege
|
|
||||||
|
|
||||||
SYNOPSIS
|
|
||||||
save_and_clear_want_privilege()
|
|
||||||
*/
|
|
||||||
|
|
||||||
void st_table_list::save_and_clear_want_privilege()
|
|
||||||
{
|
|
||||||
for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local)
|
|
||||||
{
|
|
||||||
if (tbl->table)
|
|
||||||
{
|
|
||||||
privilege_backup= tbl->table->grant.want_privilege;
|
|
||||||
tbl->table->grant.want_privilege= 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tbl->save_and_clear_want_privilege();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
restore want_privilege saved by save_and_clear_want_privilege
|
|
||||||
|
|
||||||
SYNOPSIS
|
|
||||||
restore_want_privilege()
|
|
||||||
*/
|
|
||||||
|
|
||||||
void st_table_list::restore_want_privilege()
|
|
||||||
{
|
|
||||||
for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local)
|
|
||||||
{
|
|
||||||
if (tbl->table)
|
|
||||||
tbl->table->grant.want_privilege= privilege_backup;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tbl->restore_want_privilege();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
setup fields of placeholder of merged VIEW
|
setup fields of placeholder of merged VIEW
|
||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
st_table_list::setup_ancestor()
|
st_table_list::setup_ancestor()
|
||||||
thd - thread handler
|
thd - thread handler
|
||||||
conds - condition of this JOIN
|
|
||||||
check_opt_type - WHITH CHECK OPTION type (VIEW_CHECK_NONE,
|
|
||||||
VIEW_CHECK_LOCAL, VIEW_CHECK_CASCADED)
|
|
||||||
NOTES
|
NOTES
|
||||||
ancestor is list of tables and views used by view (underlying tables/views)
|
ancestor is list of tables and views used by view (underlying tables/views)
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
It is:
|
It is:
|
||||||
- preparing translation table for view columns (fix_fields() for every
|
- preparing translation table for view columns
|
||||||
call and creation for first call)
|
|
||||||
- preparing WHERE, ON and CHECK OPTION condition (fix_fields() for every
|
|
||||||
call and merging for first call).
|
|
||||||
If there are underlying view(s) procedure first will be called for them.
|
If there are underlying view(s) procedure first will be called for them.
|
||||||
|
|
||||||
RETURN
|
RETURN
|
||||||
@ -1796,87 +1745,30 @@ void st_table_list::restore_want_privilege()
|
|||||||
TRUE - error
|
TRUE - error
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool st_table_list::setup_ancestor(THD *thd, Item **conds,
|
bool st_table_list::setup_ancestor(THD *thd)
|
||||||
uint8 check_opt_type)
|
{
|
||||||
|
DBUG_ENTER("st_table_list::setup_ancestor");
|
||||||
|
if (!field_translation)
|
||||||
{
|
{
|
||||||
Field_translator *transl;
|
Field_translator *transl;
|
||||||
SELECT_LEX *select= &view->select_lex;
|
SELECT_LEX *select= &view->select_lex;
|
||||||
SELECT_LEX *current_select_save= thd->lex->current_select;
|
|
||||||
byte *main_table_list_save= select_lex->table_list.first;
|
|
||||||
Item *item;
|
Item *item;
|
||||||
TABLE_LIST *tbl;
|
TABLE_LIST *tbl;
|
||||||
List_iterator_fast<Item> it(select->item_list);
|
List_iterator_fast<Item> it(select->item_list);
|
||||||
uint i= 0;
|
uint field_count= 0;
|
||||||
enum sub_select_type linkage_save=
|
|
||||||
select_lex->master_unit()->first_select()->linkage;
|
|
||||||
bool save_set_query_id= thd->set_query_id;
|
|
||||||
bool save_wrapper= select_lex->no_wrap_view_item;
|
|
||||||
bool save_allow_sum_func= thd->allow_sum_func;
|
|
||||||
bool res= FALSE;
|
|
||||||
DBUG_ENTER("st_table_list::setup_ancestor");
|
|
||||||
|
|
||||||
if (check_stack_overrun(thd, STACK_MIN_SIZE, (char *)&res))
|
if (check_stack_overrun(thd, STACK_MIN_SIZE, (char *)&field_count))
|
||||||
return TRUE;
|
{
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
for (tbl= ancestor; tbl; tbl= tbl->next_local)
|
for (tbl= ancestor; tbl; tbl= tbl->next_local)
|
||||||
{
|
{
|
||||||
if (tbl->ancestor &&
|
if (tbl->ancestor &&
|
||||||
tbl->setup_ancestor(thd, conds,
|
tbl->setup_ancestor(thd))
|
||||||
(check_opt_type == VIEW_CHECK_CASCADED ?
|
{
|
||||||
VIEW_CHECK_CASCADED :
|
|
||||||
VIEW_CHECK_NONE)))
|
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
We have to ensure that inside the view we are not referring to any
|
|
||||||
table outside of the view. We do it by changing the pointers used
|
|
||||||
by fix_fields to look up tables so that only tables and views in
|
|
||||||
view are seen. We also set linkage to DERIVED_TABLE_TYPE as a barrier
|
|
||||||
so that we stop resolving fields as this level.
|
|
||||||
*/
|
|
||||||
thd->lex->current_select= select_lex;
|
|
||||||
select_lex->table_list.first= (byte *)ancestor;
|
|
||||||
select_lex->master_unit()->first_select()->linkage= DERIVED_TABLE_TYPE;
|
|
||||||
|
|
||||||
if (field_translation)
|
|
||||||
{
|
|
||||||
DBUG_PRINT("info", ("there are already translation table"));
|
|
||||||
|
|
||||||
select_lex->no_wrap_view_item= 1;
|
|
||||||
|
|
||||||
thd->set_query_id= 1;
|
|
||||||
/* this view was prepared already on previous PS/SP execution */
|
|
||||||
Field_translator *end= field_translation + select->item_list.elements;
|
|
||||||
/* real rights will be checked in VIEW field */
|
|
||||||
save_and_clear_want_privilege();
|
|
||||||
/* aggregate function are allowed */
|
|
||||||
thd->allow_sum_func= 1;
|
|
||||||
for (transl= field_translation; transl < end; transl++)
|
|
||||||
{
|
|
||||||
if (!transl->item->fixed &&
|
|
||||||
transl->item->fix_fields(thd, ancestor, &transl->item))
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
for (tbl= ancestor; tbl; tbl= tbl->next_local)
|
|
||||||
{
|
|
||||||
if (tbl->on_expr && !tbl->on_expr->fixed &&
|
|
||||||
tbl->on_expr->fix_fields(thd, ancestor, &tbl->on_expr))
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
if (where && !where->fixed && where->fix_fields(thd, ancestor, &where))
|
|
||||||
goto err;
|
|
||||||
if (check_option && !check_option->fixed &&
|
|
||||||
check_option->fix_fields(thd, ancestor, &check_option))
|
|
||||||
goto err;
|
|
||||||
restore_want_privilege();
|
|
||||||
|
|
||||||
/* WHERE/ON resolved => we can rename fields */
|
|
||||||
for (transl= field_translation; transl < end; transl++)
|
|
||||||
{
|
|
||||||
transl->item->rename((char *)transl->name);
|
|
||||||
}
|
|
||||||
goto ok;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create view fields translation table */
|
/* Create view fields translation table */
|
||||||
@ -1886,73 +1778,81 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds,
|
|||||||
alloc(select->item_list.elements *
|
alloc(select->item_list.elements *
|
||||||
sizeof(Field_translator)))))
|
sizeof(Field_translator)))))
|
||||||
{
|
{
|
||||||
res= TRUE;
|
DBUG_RETURN(TRUE);
|
||||||
goto ok; // Restore thd
|
|
||||||
}
|
}
|
||||||
|
|
||||||
select_lex->no_wrap_view_item= 1;
|
|
||||||
|
|
||||||
/*
|
|
||||||
Resolve all view items against ancestor table.
|
|
||||||
|
|
||||||
TODO: do it only for real used fields "on demand" to mark really
|
|
||||||
used fields correctly.
|
|
||||||
*/
|
|
||||||
thd->set_query_id= 1;
|
|
||||||
/* real rights will be checked in VIEW field */
|
|
||||||
save_and_clear_want_privilege();
|
|
||||||
/* aggregate function are allowed */
|
|
||||||
thd->allow_sum_func= 1;
|
|
||||||
while ((item= it++))
|
while ((item= it++))
|
||||||
{
|
{
|
||||||
/* save original name of view column */
|
transl[field_count].name= item->name;
|
||||||
char *name= item->name;
|
transl[field_count++].item= item;
|
||||||
transl[i].item= item;
|
|
||||||
if (!item->fixed && item->fix_fields(thd, ancestor, &transl[i].item))
|
|
||||||
goto err;
|
|
||||||
/* set new item get in fix fields and original column name */
|
|
||||||
transl[i++].name= name;
|
|
||||||
}
|
}
|
||||||
field_translation= transl;
|
field_translation= transl;
|
||||||
/* TODO: sort this list? Use hash for big number of fields */
|
field_translation_end= transl + field_count;
|
||||||
|
/* TODO: use hash for big number of fields */
|
||||||
|
|
||||||
for (tbl= ancestor; tbl; tbl= tbl->next_local)
|
/* full text function moving to current select */
|
||||||
|
if (view->select_lex.ftfunc_list->elements)
|
||||||
{
|
{
|
||||||
if (tbl->on_expr && !tbl->on_expr->fixed &&
|
Item_func_match *ifm;
|
||||||
tbl->on_expr->fix_fields(thd, ancestor, &tbl->on_expr))
|
SELECT_LEX *current_select= thd->lex->current_select;
|
||||||
goto err;
|
List_iterator_fast<Item_func_match>
|
||||||
|
li(*(view->select_lex.ftfunc_list));
|
||||||
|
while ((ifm= li++))
|
||||||
|
current_select->ftfunc_list->push_front(ifm);
|
||||||
}
|
}
|
||||||
if (where ||
|
}
|
||||||
(check_opt_type == VIEW_CHECK_CASCADED &&
|
DBUG_RETURN(FALSE);
|
||||||
ancestor->check_option))
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Prepare where expression of view
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
st_table_list::prep_where()
|
||||||
|
thd - thread handler
|
||||||
|
conds - condition of this JOIN
|
||||||
|
no_where_clause - do not build WHERE or ON outer qwery do not need it
|
||||||
|
(it is INSERT), we do not need conds if this flag is set
|
||||||
|
|
||||||
|
NOTE: have to be called befor CHECK OPTION preparation, because it makes
|
||||||
|
fix_fields for view WHERE clause
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
FALSE - OK
|
||||||
|
TRUE - error
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool st_table_list::prep_where(THD *thd, Item **conds,
|
||||||
|
bool no_where_clause)
|
||||||
{
|
{
|
||||||
Query_arena *arena= thd->current_arena, backup;
|
DBUG_ENTER("st_table_list::prep_where");
|
||||||
TABLE_LIST *tbl= this;
|
|
||||||
if (arena->is_conventional())
|
|
||||||
arena= 0; // For easier test
|
|
||||||
|
|
||||||
if (where && !where->fixed && where->fix_fields(thd, ancestor, &where))
|
for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local)
|
||||||
goto err;
|
|
||||||
|
|
||||||
if (arena)
|
|
||||||
thd->set_n_backup_item_arena(arena, &backup);
|
|
||||||
|
|
||||||
if (check_opt_type)
|
|
||||||
{
|
{
|
||||||
|
if (tbl->view && tbl->prep_where(thd, conds, no_where_clause))
|
||||||
|
{
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (where)
|
if (where)
|
||||||
check_option= where->copy_andor_structure(thd);
|
|
||||||
if (check_opt_type == VIEW_CHECK_CASCADED)
|
|
||||||
{
|
{
|
||||||
check_option= and_conds(check_option, ancestor->check_option);
|
if (!where->fixed && where->fix_fields(thd, &where))
|
||||||
}
|
{
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
check that it is not VIEW in which we insert with INSERT SELECT
|
check that it is not VIEW in which we insert with INSERT SELECT
|
||||||
(in this case we can't add view WHERE condition to main SELECT_LEX)
|
(in this case we can't add view WHERE condition to main SELECT_LEX)
|
||||||
*/
|
*/
|
||||||
if (where && !no_where_clause)
|
if (!no_where_clause && !where_processed)
|
||||||
{
|
{
|
||||||
|
TABLE_LIST *tbl= this;
|
||||||
|
Query_arena *arena= thd->current_arena, backup;
|
||||||
|
arena= thd->change_arena_if_needed(&backup); // For easier test
|
||||||
|
|
||||||
/* Go up to join tree and try to find left join */
|
/* Go up to join tree and try to find left join */
|
||||||
for (; tbl; tbl= tbl->embedding)
|
for (; tbl; tbl= tbl->embedding)
|
||||||
{
|
{
|
||||||
@ -1969,72 +1869,107 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (tbl == 0)
|
if (tbl == 0)
|
||||||
{
|
|
||||||
if (outer_join)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
Store WHERE condition to ON expression for outer join, because
|
|
||||||
we can't use WHERE to correctly execute left joins on VIEWs and
|
|
||||||
this expression will not be moved to WHERE condition (i.e. will
|
|
||||||
be clean correctly for PS/SP)
|
|
||||||
*/
|
|
||||||
on_expr= and_conds(on_expr, where);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
It is conds of JOIN, but it will be stored in
|
|
||||||
st_select_lex::prep_where for next reexecution
|
|
||||||
*/
|
|
||||||
*conds= and_conds(*conds, where);
|
*conds= and_conds(*conds, where);
|
||||||
}
|
if (arena)
|
||||||
|
thd->restore_backup_item_arena(arena, &backup);
|
||||||
|
where_processed= TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arena)
|
DBUG_RETURN(FALSE);
|
||||||
thd->restore_backup_item_arena(arena, &backup);
|
|
||||||
}
|
}
|
||||||
restore_want_privilege();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
fix_fields do not need tables, because new are only AND operation and we
|
Prepare check option expression of table
|
||||||
just need recollect statistics
|
|
||||||
|
SYNOPSIS
|
||||||
|
st_table_list::prep_check_option()
|
||||||
|
thd - thread handler
|
||||||
|
check_opt_type - WITH CHECK OPTION type (VIEW_CHECK_NONE,
|
||||||
|
VIEW_CHECK_LOCAL, VIEW_CHECK_CASCADED)
|
||||||
|
we use this parameter instead of direct check of
|
||||||
|
effective_with_check to change type of underlying
|
||||||
|
views to VIEW_CHECK_CASCADED if outer view have
|
||||||
|
such option and prevent processing of underlying
|
||||||
|
view check options if outer view have just
|
||||||
|
VIEW_CHECK_LOCAL option.
|
||||||
|
|
||||||
|
NOTE
|
||||||
|
This method build check options for every call
|
||||||
|
(usual execution or every SP/PS call)
|
||||||
|
This method have to be called after WHERE preparation
|
||||||
|
(st_table_list::prep_where)
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
FALSE - OK
|
||||||
|
TRUE - error
|
||||||
*/
|
*/
|
||||||
if (check_option && !check_option->fixed &&
|
|
||||||
check_option->fix_fields(thd, 0, &check_option))
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
/* WHERE/ON resolved => we can rename fields */
|
bool st_table_list::prep_check_option(THD *thd, uint8 check_opt_type)
|
||||||
{
|
{
|
||||||
Field_translator *end= field_translation + select->item_list.elements;
|
DBUG_ENTER("st_table_list::prep_check_option");
|
||||||
for (transl= field_translation; transl < end; transl++)
|
|
||||||
|
for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local)
|
||||||
{
|
{
|
||||||
transl->item->rename((char *)transl->name);
|
/* see comment of check_opt_type parameter */
|
||||||
|
if (tbl->view &&
|
||||||
|
tbl->prep_check_option(thd,
|
||||||
|
((check_opt_type == VIEW_CHECK_CASCADED) ?
|
||||||
|
VIEW_CHECK_CASCADED :
|
||||||
|
VIEW_CHECK_NONE)))
|
||||||
|
{
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* full text function moving to current select */
|
if (check_opt_type)
|
||||||
if (view->select_lex.ftfunc_list->elements)
|
|
||||||
{
|
{
|
||||||
Query_arena *arena= thd->current_arena, backup;
|
Item *item= 0;
|
||||||
if (arena->is_conventional())
|
if (where)
|
||||||
arena= 0; // For easier test
|
{
|
||||||
else
|
DBUG_ASSERT(where->fixed);
|
||||||
thd->set_n_backup_item_arena(arena, &backup);
|
item= where->copy_andor_structure(thd);
|
||||||
|
}
|
||||||
Item_func_match *ifm;
|
if (check_opt_type == VIEW_CHECK_CASCADED)
|
||||||
List_iterator_fast<Item_func_match>
|
{
|
||||||
li(*(view->select_lex.ftfunc_list));
|
for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local)
|
||||||
while ((ifm= li++))
|
{
|
||||||
current_select_save->ftfunc_list->push_front(ifm);
|
if (tbl->check_option)
|
||||||
if (arena)
|
item= and_conds(item, tbl->check_option);
|
||||||
thd->restore_backup_item_arena(arena, &backup);
|
}
|
||||||
|
}
|
||||||
|
if (item)
|
||||||
|
thd->change_item_tree(&check_option, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
goto ok;
|
if (check_option)
|
||||||
|
{
|
||||||
|
const char *save_where= thd->where;
|
||||||
|
thd->where= "check option";
|
||||||
|
if (!check_option->fixed &&
|
||||||
|
check_option->fix_fields(thd, &check_option) ||
|
||||||
|
check_option->check_cols(1))
|
||||||
|
{
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
thd->where= save_where;
|
||||||
|
}
|
||||||
|
DBUG_RETURN(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
err:
|
|
||||||
res= TRUE;
|
/*
|
||||||
|
Hide errors which show view underlying table information
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
st_table_list::hide_view_error()
|
||||||
|
thd thread handler
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
void st_table_list::hide_view_error(THD *thd)
|
||||||
|
{
|
||||||
/* Hide "Unknown column" or "Unknown function" error */
|
/* Hide "Unknown column" or "Unknown function" error */
|
||||||
if (thd->net.last_errno == ER_BAD_FIELD_ERROR ||
|
if (thd->net.last_errno == ER_BAD_FIELD_ERROR ||
|
||||||
thd->net.last_errno == ER_SP_DOES_NOT_EXIST)
|
thd->net.last_errno == ER_SP_DOES_NOT_EXIST)
|
||||||
@ -2042,15 +1977,12 @@ err:
|
|||||||
thd->clear_error();
|
thd->clear_error();
|
||||||
my_error(ER_VIEW_INVALID, MYF(0), view_db.str, view_name.str);
|
my_error(ER_VIEW_INVALID, MYF(0), view_db.str, view_name.str);
|
||||||
}
|
}
|
||||||
|
else if (thd->net.last_errno == ER_NO_DEFAULT_FOR_FIELD)
|
||||||
ok:
|
{
|
||||||
select_lex->no_wrap_view_item= save_wrapper;
|
thd->clear_error();
|
||||||
thd->lex->current_select= current_select_save;
|
// TODO: make correct error message
|
||||||
select_lex->table_list.first= main_table_list_save;
|
my_error(ER_NO_DEFAULT_FOR_VIEW_FIELD, MYF(0), view_db.str, view_name.str);
|
||||||
select_lex->master_unit()->first_select()->linkage= linkage_save;
|
}
|
||||||
thd->set_query_id= save_set_query_id;
|
|
||||||
thd->allow_sum_func= save_allow_sum_func;
|
|
||||||
DBUG_RETURN(res);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2094,9 +2026,9 @@ void st_table_list::cleanup_items()
|
|||||||
if (!field_translation)
|
if (!field_translation)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Field_translator *end= (field_translation +
|
for (Field_translator *transl= field_translation;
|
||||||
view->select_lex.item_list.elements);
|
transl < field_translation_end;
|
||||||
for (Field_translator *transl= field_translation; transl < end; transl++)
|
transl++)
|
||||||
transl->item->walk(&Item::cleanup_processor, 0);
|
transl->item->walk(&Item::cleanup_processor, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2209,8 +2141,9 @@ bool st_table_list::set_insert_values(MEM_ROOT *mem_root)
|
|||||||
|
|
||||||
void Field_iterator_view::set(TABLE_LIST *table)
|
void Field_iterator_view::set(TABLE_LIST *table)
|
||||||
{
|
{
|
||||||
|
view= table;
|
||||||
ptr= table->field_translation;
|
ptr= table->field_translation;
|
||||||
array_end= ptr + table->view->select_lex.item_list.elements;
|
array_end= table->field_translation_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2220,9 +2153,9 @@ const char *Field_iterator_table::name()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Item *Field_iterator_table::item(THD *thd)
|
Item *Field_iterator_table::create_item(THD *thd)
|
||||||
{
|
{
|
||||||
return new Item_field(thd, *ptr);
|
return new Item_field(thd, &thd->lex->current_select->context, *ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2232,6 +2165,51 @@ const char *Field_iterator_view::name()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Item *Field_iterator_view::create_item(THD *thd)
|
||||||
|
{
|
||||||
|
return create_view_field(thd, view, &ptr->item, ptr->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
Item *create_view_field(THD *thd, TABLE_LIST *view, Item **field_ref,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
bool save_wrapper= thd->lex->select_lex.no_wrap_view_item;
|
||||||
|
Item *field= *field_ref;
|
||||||
|
DBUG_ENTER("create_view_field");
|
||||||
|
|
||||||
|
if (view->schema_table_reformed)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
In case of SHOW command (schema_table_reformed set) all items are
|
||||||
|
fixed
|
||||||
|
*/
|
||||||
|
DBUG_ASSERT(field && field->fixed);
|
||||||
|
DBUG_RETURN(field);
|
||||||
|
}
|
||||||
|
|
||||||
|
DBUG_ASSERT(field);
|
||||||
|
thd->lex->current_select->no_wrap_view_item= TRUE;
|
||||||
|
if (!field->fixed)
|
||||||
|
{
|
||||||
|
if (field->fix_fields(thd, field_ref))
|
||||||
|
{
|
||||||
|
thd->lex->current_select->no_wrap_view_item= save_wrapper;
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
field= *field_ref;
|
||||||
|
}
|
||||||
|
thd->lex->current_select->no_wrap_view_item= save_wrapper;
|
||||||
|
if (thd->lex->current_select->no_wrap_view_item)
|
||||||
|
{
|
||||||
|
DBUG_RETURN(field);
|
||||||
|
}
|
||||||
|
Item *item= new Item_direct_view_ref(&view->view->select_lex.context,
|
||||||
|
field_ref, view->view_name.str,
|
||||||
|
name);
|
||||||
|
DBUG_RETURN(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
** Instansiate templates
|
** Instansiate templates
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
43
sql/table.h
43
sql/table.h
@ -329,9 +329,13 @@ typedef struct st_schema_table
|
|||||||
#define VIEW_CHECK_SKIP 2
|
#define VIEW_CHECK_SKIP 2
|
||||||
|
|
||||||
struct st_lex;
|
struct st_lex;
|
||||||
|
struct st_table_list;
|
||||||
class select_union;
|
class select_union;
|
||||||
class TMP_TABLE_PARAM;
|
class TMP_TABLE_PARAM;
|
||||||
|
|
||||||
|
Item *create_view_field(THD *thd, st_table_list *view, Item **field_ref,
|
||||||
|
const char *name);
|
||||||
|
|
||||||
struct Field_translator
|
struct Field_translator
|
||||||
{
|
{
|
||||||
Item *item;
|
Item *item;
|
||||||
@ -384,6 +388,8 @@ typedef struct st_table_list
|
|||||||
st_select_lex *select_lex;
|
st_select_lex *select_lex;
|
||||||
st_lex *view; /* link on VIEW lex for merging */
|
st_lex *view; /* link on VIEW lex for merging */
|
||||||
Field_translator *field_translation; /* array of VIEW fields */
|
Field_translator *field_translation; /* array of VIEW fields */
|
||||||
|
/* pointer to element after last one in translation table above */
|
||||||
|
Field_translator *field_translation_end;
|
||||||
/* list of ancestor(s) of this table (underlying table(s)/view(s) */
|
/* list of ancestor(s) of this table (underlying table(s)/view(s) */
|
||||||
st_table_list *ancestor;
|
st_table_list *ancestor;
|
||||||
/* most upper view this table belongs to */
|
/* most upper view this table belongs to */
|
||||||
@ -408,8 +414,7 @@ typedef struct st_table_list
|
|||||||
algorithm)
|
algorithm)
|
||||||
*/
|
*/
|
||||||
uint8 effective_with_check;
|
uint8 effective_with_check;
|
||||||
uint effective_algorithm; /* which algorithm was really used */
|
uint8 effective_algorithm; /* which algorithm was really used */
|
||||||
uint privilege_backup; /* place for saving privileges */
|
|
||||||
GRANT_INFO grant;
|
GRANT_INFO grant;
|
||||||
/* data need by some engines in query cache*/
|
/* data need by some engines in query cache*/
|
||||||
ulonglong engine_data;
|
ulonglong engine_data;
|
||||||
@ -424,7 +429,6 @@ typedef struct st_table_list
|
|||||||
bool updating; /* for replicate-do/ignore table */
|
bool updating; /* for replicate-do/ignore table */
|
||||||
bool force_index; /* prefer index over table scan */
|
bool force_index; /* prefer index over table scan */
|
||||||
bool ignore_leaves; /* preload only non-leaf nodes */
|
bool ignore_leaves; /* preload only non-leaf nodes */
|
||||||
bool no_where_clause; /* do not attach WHERE to SELECT */
|
|
||||||
table_map dep_tables; /* tables the table depends on */
|
table_map dep_tables; /* tables the table depends on */
|
||||||
table_map on_expr_dep_tables; /* tables on expression depends on */
|
table_map on_expr_dep_tables; /* tables on expression depends on */
|
||||||
struct st_nested_join *nested_join; /* if the element is a nested join */
|
struct st_nested_join *nested_join; /* if the element is a nested join */
|
||||||
@ -437,6 +441,8 @@ typedef struct st_table_list
|
|||||||
/* TRUE if this merged view contain auto_increment field */
|
/* TRUE if this merged view contain auto_increment field */
|
||||||
bool contain_auto_increment;
|
bool contain_auto_increment;
|
||||||
bool multitable_view; /* TRUE iff this is multitable view */
|
bool multitable_view; /* TRUE iff this is multitable view */
|
||||||
|
/* view where processed */
|
||||||
|
bool where_processed;
|
||||||
/* FRMTYPE_ERROR if any type is acceptable */
|
/* FRMTYPE_ERROR if any type is acceptable */
|
||||||
enum frm_type_enum required_type;
|
enum frm_type_enum required_type;
|
||||||
char timestamp_buffer[20]; /* buffer for timestamp (19+1) */
|
char timestamp_buffer[20]; /* buffer for timestamp (19+1) */
|
||||||
@ -449,16 +455,32 @@ typedef struct st_table_list
|
|||||||
void calc_md5(char *buffer);
|
void calc_md5(char *buffer);
|
||||||
void set_ancestor();
|
void set_ancestor();
|
||||||
int view_check_option(THD *thd, bool ignore_failure);
|
int view_check_option(THD *thd, bool ignore_failure);
|
||||||
bool setup_ancestor(THD *thd, Item **conds, uint8 check_option);
|
bool setup_ancestor(THD *thd);
|
||||||
void cleanup_items();
|
void cleanup_items();
|
||||||
bool placeholder() {return derived || view; }
|
bool placeholder() {return derived || view; }
|
||||||
void print(THD *thd, String *str);
|
void print(THD *thd, String *str);
|
||||||
void save_and_clear_want_privilege();
|
|
||||||
void restore_want_privilege();
|
|
||||||
bool check_single_table(st_table_list **table, table_map map,
|
bool check_single_table(st_table_list **table, table_map map,
|
||||||
st_table_list *view);
|
st_table_list *view);
|
||||||
bool set_insert_values(MEM_ROOT *mem_root);
|
bool set_insert_values(MEM_ROOT *mem_root);
|
||||||
|
void hide_view_error(THD *thd);
|
||||||
st_table_list *find_underlying_table(TABLE *table);
|
st_table_list *find_underlying_table(TABLE *table);
|
||||||
|
inline bool prepare_check_option(THD *thd)
|
||||||
|
{
|
||||||
|
bool res= FALSE;
|
||||||
|
if (effective_with_check)
|
||||||
|
res= prep_check_option(thd, effective_with_check);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
inline bool prepare_where(THD *thd, Item **conds,
|
||||||
|
bool no_where_clause)
|
||||||
|
{
|
||||||
|
if (effective_algorithm == VIEW_ALGORITHM_MERGE)
|
||||||
|
return prep_where(thd, conds, no_where_clause);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
bool prep_check_option(THD *thd, uint8 check_opt_type);
|
||||||
|
bool prep_where(THD *thd, Item **conds, bool no_where_clause);
|
||||||
} TABLE_LIST;
|
} TABLE_LIST;
|
||||||
|
|
||||||
class Item;
|
class Item;
|
||||||
@ -471,7 +493,7 @@ public:
|
|||||||
virtual void next()= 0;
|
virtual void next()= 0;
|
||||||
virtual bool end_of_fields()= 0; /* Return 1 at end of list */
|
virtual bool end_of_fields()= 0; /* Return 1 at end of list */
|
||||||
virtual const char *name()= 0;
|
virtual const char *name()= 0;
|
||||||
virtual Item *item(THD *)= 0;
|
virtual Item *create_item(THD *)= 0;
|
||||||
virtual Field *field()= 0;
|
virtual Field *field()= 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -486,7 +508,7 @@ public:
|
|||||||
void next() { ptr++; }
|
void next() { ptr++; }
|
||||||
bool end_of_fields() { return *ptr == 0; }
|
bool end_of_fields() { return *ptr == 0; }
|
||||||
const char *name();
|
const char *name();
|
||||||
Item *item(THD *thd);
|
Item *create_item(THD *thd);
|
||||||
Field *field() { return *ptr; }
|
Field *field() { return *ptr; }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -494,15 +516,18 @@ public:
|
|||||||
class Field_iterator_view: public Field_iterator
|
class Field_iterator_view: public Field_iterator
|
||||||
{
|
{
|
||||||
Field_translator *ptr, *array_end;
|
Field_translator *ptr, *array_end;
|
||||||
|
TABLE_LIST *view;
|
||||||
public:
|
public:
|
||||||
Field_iterator_view() :ptr(0), array_end(0) {}
|
Field_iterator_view() :ptr(0), array_end(0) {}
|
||||||
void set(TABLE_LIST *table);
|
void set(TABLE_LIST *table);
|
||||||
void next() { ptr++; }
|
void next() { ptr++; }
|
||||||
bool end_of_fields() { return ptr == array_end; }
|
bool end_of_fields() { return ptr == array_end; }
|
||||||
const char *name();
|
const char *name();
|
||||||
Item *item(THD *thd) { return ptr->item; }
|
Item *create_item(THD *thd);
|
||||||
Item **item_ptr() {return &ptr->item; }
|
Item **item_ptr() {return &ptr->item; }
|
||||||
Field *field() { return 0; }
|
Field *field() { return 0; }
|
||||||
|
|
||||||
|
inline Item *item() { return ptr->item; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user