Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
mariadb
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
mariadb
Commits
7a7c1f79
Commit
7a7c1f79
authored
Feb 16, 2006
by
unknown
Browse files
Options
Browse Files
Download
Plain Diff
Merge
sql/item.cc: Auto merged sql/item.h: Auto merged mysql-test/t/disabled.def: SCCS merged
parents
74f6299e
de0c65dd
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
285 additions
and
195 deletions
+285
-195
mysql-test/t/disabled.def
mysql-test/t/disabled.def
+0
-1
sql/item.cc
sql/item.cc
+283
-194
sql/item.h
sql/item.h
+1
-0
sql/item_subselect.h
sql/item_subselect.h
+1
-0
No files found.
mysql-test/t/disabled.def
View file @
7a7c1f79
...
...
@@ -11,5 +11,4 @@
##############################################################################
sp-goto : GOTO is currently is disabled - will be fixed in the future
subselect : Bug#15706
ndb_load : Bug#17233
sql/item.cc
View file @
7a7c1f79
...
...
@@ -3211,30 +3211,21 @@ resolve_ref_in_select_and_group(THD *thd, Item_ident *ref, SELECT_LEX *select)
/*
Resolve the name of a column reference.
Resolve the name of a
n outer select
column reference.
SYNOPSIS
Item_field::fix_
fields
()
Item_field::fix_
outer_field
()
thd [in] current thread
from_field [in/out] found field reference or (Field*)not_found_field
reference [in/out] view column if this item was resolved to a view column
DESCRIPTION
The method resolves the column reference represented by 'this' as a column
present in one of: FROM clause, SELECT clause, GROUP BY clause of a query
Q, or in outer queries that contain Q.
present in outer selects that contain current select.
NOTES
The name resolution algorithm used is (where [T_j] is an optional table
name that qualifies the column name):
resolve_column_reference([T_j].col_ref_i)
{
search for a column or derived column named col_ref_i
[in table T_j] in the FROM clause of Q;
This is the inner loop of Item_field::fix_fields:
if such a column is NOT found AND // Lookup in outer queries.
there are outer queries
{
for each outer query Q_k beginning from the inner-most one
{
search for a column or derived column named col_ref_i
...
...
@@ -3244,54 +3235,25 @@ resolve_ref_in_select_and_group(THD *thd, Item_ident *ref, SELECT_LEX *select)
Search for a column or derived column named col_ref_i
[in table T_j] in the SELECT and GROUP clauses of Q_k.
}
}
}
Notice that compared to Item_ref::fix_fields, here we first search the FROM
clause, and then we search the SELECT and GROUP BY clauses.
IMPLEMENTATION
In prepared statements, because of cache, find_field_in_tables()
can resolve fields even if they don't belong to current context.
In this case this method only finds appropriate context and marks
current select as dependent. The found reference of field should be
provided in 'from_field'.
RETURN
TRUE if error
FALSE on success
1 - column succefully resolved and fix_fields() should continue.
0 - column fully fixed and fix_fields() should return FALSE
-1 - error occured
*/
bool
Item_field
::
fix_fields
(
THD
*
th
d
,
Item
**
reference
)
int
Item_field
::
fix_outer_field
(
THD
*
thd
,
Field
**
from_fiel
d
,
Item
**
reference
)
{
enum_parsing_place
place
=
NO_MATTER
;
DBUG_ASSERT
(
fixed
==
0
);
if
(
!
field
)
// If field is not checked
{
bool
field_found
=
(
*
from_field
!=
not_found_field
);
bool
upward_lookup
=
FALSE
;
Field
*
from_field
=
(
Field
*
)
not_found_field
;
/*
In case of view, find_field_in_tables() write pointer to view field
expression to 'reference', i.e. it substitute that expression instead
of this Item_field
*/
if
((
from_field
=
find_field_in_tables
(
thd
,
this
,
context
->
first_name_resolution_table
,
context
->
last_name_resolution_table
,
reference
,
IGNORE_EXCEPT_NON_UNIQUE
,
!
any_privileges
,
TRUE
))
==
not_found_field
)
{
/* Look up in current select's item_list to find aliased fields */
if
(
thd
->
lex
->
current_select
->
is_item_list_lookup
)
{
uint
counter
;
bool
not_used
;
Item
**
res
=
find_item_in_list
(
this
,
thd
->
lex
->
current_select
->
item_list
,
&
counter
,
REPORT_EXCEPT_NOT_FOUND
,
&
not_used
);
if
(
res
!=
(
Item
**
)
not_found_item
&&
(
*
res
)
->
type
()
==
Item
::
FIELD_ITEM
)
{
set_field
((
*
((
Item_field
**
)
res
))
->
field
);
return
0
;
}
}
/*
If there are outer contexts (outer selects, but current select is
...
...
@@ -3316,12 +3278,19 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
upward_lookup
=
TRUE
;
place
=
prev_subselect_item
->
parsing_place
;
/*
If outer_field is set, field was already found by first call
to find_field_in_tables(). Only need to find appropriate context.
*/
if
(
field_found
&&
outer_context
->
select_lex
!=
cached_table
->
select_lex
)
continue
;
/*
In case of a view, find_field_in_tables() writes the pointer to
the found view field into '*reference', in other words, it
substitutes this Item_field with the found expression.
*/
if
((
from_field
=
find_field_in_tables
(
thd
,
this
,
if
(
field_found
||
(
*
from_field
=
find_field_in_tables
(
thd
,
this
,
outer_context
->
first_name_resolution_table
,
outer_context
->
...
...
@@ -3331,11 +3300,11 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
TRUE
,
TRUE
))
!=
not_found_field
)
{
if
(
from_field
)
if
(
*
from_field
)
{
if
(
from_field
!=
view_ref_found
)
if
(
*
from_field
!=
view_ref_found
)
{
prev_subselect_item
->
used_tables_cache
|=
from_field
->
table
->
map
;
prev_subselect_item
->
used_tables_cache
|=
(
*
from_field
)
->
table
->
map
;
prev_subselect_item
->
const_item_cache
=
0
;
if
(
thd
->
lex
->
in_sum_func
&&
thd
->
lex
->
in_sum_func
->
nest_level
==
...
...
@@ -3344,13 +3313,13 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
Item
::
Type
type
=
(
*
reference
)
->
type
();
set_if_bigger
(
thd
->
lex
->
in_sum_func
->
max_arg_level
,
select
->
nest_level
);
set_field
(
from_field
);
set_field
(
*
from_field
);
fixed
=
1
;
mark_as_dependent
(
thd
,
last_checked_context
->
select_lex
,
context
->
select_lex
,
this
,
((
type
==
REF_ITEM
||
type
==
FIELD_ITEM
)
?
(
Item_ident
*
)
(
*
reference
)
:
0
));
return
FALSE
;
return
0
;
}
}
else
...
...
@@ -3371,7 +3340,7 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
does it by assigning the new value to *reference), so now
we can return from this function.
*/
return
FALSE
;
return
0
;
}
}
break
;
...
...
@@ -3381,7 +3350,7 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
if
(
outer_context
->
resolve_in_select_list
)
{
if
(
!
(
ref
=
resolve_ref_in_select_and_group
(
thd
,
this
,
select
)))
goto
error
;
/* Some error occurred (e.g. ambiguous names). */
return
-
1
;
/* Some error occurred (e.g. ambiguous names). */
if
(
ref
!=
not_found_item
)
{
DBUG_ASSERT
(
*
ref
&&
(
*
ref
)
->
fixed
);
...
...
@@ -3401,9 +3370,9 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
}
DBUG_ASSERT
(
ref
!=
0
);
if
(
!
from_field
)
goto
error
;
if
(
ref
==
not_found_item
&&
from_field
==
not_found_field
)
if
(
!*
from_field
)
return
-
1
;
if
(
ref
==
not_found_item
&&
*
from_field
==
not_found_field
)
{
if
(
upward_lookup
)
{
...
...
@@ -3420,7 +3389,7 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
!
any_privileges
&&
TRUE
,
TRUE
);
}
goto
error
;
return
-
1
;
}
else
if
(
ref
!=
not_found_item
)
{
...
...
@@ -3444,7 +3413,7 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
(
char
*
)
field_name
));
*
ref
=
save
;
if
(
!
rf
)
goto
error
;
return
-
1
;
thd
->
change_item_tree
(
reference
,
rf
);
/*
rf is Item_ref => never substitute other items (in this case)
...
...
@@ -3452,12 +3421,12 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
*/
DBUG_ASSERT
(
!
rf
->
fixed
);
// Assured by Item_ref()
if
(
rf
->
fix_fields
(
thd
,
reference
)
||
rf
->
check_cols
(
1
))
goto
error
;
return
-
1
;
mark_as_dependent
(
thd
,
last_checked_context
->
select_lex
,
context
->
select_lex
,
this
,
rf
);
return
FALSE
;
return
0
;
}
else
{
...
...
@@ -3471,7 +3440,7 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
(
cached_table
->
db
[
0
]
?
cached_table
->
db
:
0
),
(
char
*
)
cached_table
->
alias
,
(
char
*
)
field_name
);
if
(
!
rf
)
goto
error
;
return
-
1
;
thd
->
change_item_tree
(
reference
,
rf
);
/*
rf is Item_ref => never substitute other items (in this case)
...
...
@@ -3479,10 +3448,100 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
*/
DBUG_ASSERT
(
!
rf
->
fixed
);
// Assured by Item_ref()
if
(
rf
->
fix_fields
(
thd
,
reference
)
||
rf
->
check_cols
(
1
))
goto
error
;
return
FALSE
;
return
-
1
;
return
0
;
}
}
return
1
;
}
/*
Resolve the name of a column reference.
SYNOPSIS
Item_field::fix_fields()
thd [in] current thread
reference [in/out] view column if this item was resolved to a view column
DESCRIPTION
The method resolves the column reference represented by 'this' as a column
present in one of: FROM clause, SELECT clause, GROUP BY clause of a query
Q, or in outer queries that contain Q.
NOTES
The name resolution algorithm used is (where [T_j] is an optional table
name that qualifies the column name):
resolve_column_reference([T_j].col_ref_i)
{
search for a column or derived column named col_ref_i
[in table T_j] in the FROM clause of Q;
if such a column is NOT found AND // Lookup in outer queries.
there are outer queries
{
for each outer query Q_k beginning from the inner-most one
{
search for a column or derived column named col_ref_i
[in table T_j] in the FROM clause of Q_k;
if such a column is not found
Search for a column or derived column named col_ref_i
[in table T_j] in the SELECT and GROUP clauses of Q_k.
}
}
}
Notice that compared to Item_ref::fix_fields, here we first search the FROM
clause, and then we search the SELECT and GROUP BY clauses.
RETURN
TRUE if error
FALSE on success
*/
bool
Item_field
::
fix_fields
(
THD
*
thd
,
Item
**
reference
)
{
DBUG_ASSERT
(
fixed
==
0
);
if
(
!
field
)
// If field is not checked
{
Field
*
from_field
=
(
Field
*
)
not_found_field
;
bool
outer_fixed
=
false
;
/*
In case of view, find_field_in_tables() write pointer to view field
expression to 'reference', i.e. it substitute that expression instead
of this Item_field
*/
if
((
from_field
=
find_field_in_tables
(
thd
,
this
,
context
->
first_name_resolution_table
,
context
->
last_name_resolution_table
,
reference
,
IGNORE_EXCEPT_NON_UNIQUE
,
!
any_privileges
,
TRUE
))
==
not_found_field
)
{
int
ret
;
/* Look up in current select's item_list to find aliased fields */
if
(
thd
->
lex
->
current_select
->
is_item_list_lookup
)
{
uint
counter
;
bool
not_used
;
Item
**
res
=
find_item_in_list
(
this
,
thd
->
lex
->
current_select
->
item_list
,
&
counter
,
REPORT_EXCEPT_NOT_FOUND
,
&
not_used
);
if
(
res
!=
(
Item
**
)
not_found_item
&&
(
*
res
)
->
type
()
==
Item
::
FIELD_ITEM
)
{
set_field
((
*
((
Item_field
**
)
res
))
->
field
);
return
0
;
}
}
if
((
ret
=
fix_outer_field
(
thd
,
&
from_field
,
reference
))
<
0
)
goto
error
;
else
if
(
!
ret
)
return
FALSE
;
outer_fixed
=
TRUE
;
}
else
if
(
!
from_field
)
goto
error
;
...
...
@@ -3502,6 +3561,17 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
if
(
from_field
==
view_ref_found
)
return
FALSE
;
if
(
!
outer_fixed
&&
cached_table
&&
cached_table
->
select_lex
&&
context
->
select_lex
&&
cached_table
->
select_lex
!=
context
->
select_lex
)
{
int
ret
;
if
((
ret
=
fix_outer_field
(
thd
,
&
from_field
,
reference
))
<
0
)
goto
error
;
else
if
(
!
ret
)
return
FALSE
;
}
set_field
(
from_field
);
if
(
thd
->
lex
->
in_sum_func
&&
thd
->
lex
->
in_sum_func
->
nest_level
==
...
...
@@ -4620,6 +4690,25 @@ bool Item_ref::fix_fields(THD *thd, Item **reference)
}
if
(
from_field
!=
not_found_field
)
{
if
(
cached_table
&&
cached_table
->
select_lex
&&
outer_context
->
select_lex
&&
cached_table
->
select_lex
!=
outer_context
->
select_lex
)
{
/*
Due to cache, find_field_in_tables() can return field which
doesn't belong to provided outer_context. In this case we have
to find proper field context in order to fix field correcly.
*/
do
{
outer_context
=
outer_context
->
outer_context
;
select
=
outer_context
->
select_lex
;
prev_subselect_item
=
last_checked_context
->
select_lex
->
master_unit
()
->
item
;
last_checked_context
=
outer_context
;
}
while
(
outer_context
&&
outer_context
->
select_lex
&&
cached_table
->
select_lex
!=
outer_context
->
select_lex
);
}
prev_subselect_item
->
used_tables_cache
|=
from_field
->
table
->
map
;
prev_subselect_item
->
const_item_cache
=
0
;
break
;
...
...
sql/item.h
View file @
7a7c1f79
...
...
@@ -1161,6 +1161,7 @@ public:
inline
uint32
max_disp_length
()
{
return
field
->
max_length
();
}
Item_field
*
filed_for_view_update
()
{
return
this
;
}
Item
*
safe_charset_converter
(
CHARSET_INFO
*
tocs
);
int
fix_outer_field
(
THD
*
thd
,
Field
**
field
,
Item
**
reference
);
friend
class
Item_default_value
;
friend
class
Item_insert_value
;
friend
class
st_select_lex_unit
;
...
...
sql/item_subselect.h
View file @
7a7c1f79
...
...
@@ -125,6 +125,7 @@ public:
friend
class
select_subselect
;
friend
class
Item_in_optimizer
;
friend
bool
Item_field
::
fix_fields
(
THD
*
,
Item
**
);
friend
int
Item_field
::
fix_outer_field
(
THD
*
,
Field
**
,
Item
**
);
friend
bool
Item_ref
::
fix_fields
(
THD
*
,
Item
**
);
friend
void
mark_select_range_as_dependent
(
THD
*
,
st_select_lex
*
,
st_select_lex
*
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment