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
b07aaeb2
Commit
b07aaeb2
authored
Sep 03, 2002
by
bell@sanja.is.com.ua
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
subselect with union
new error handling Item_ref bug fixed
parent
189d1dd6
Changes
25
Hide whitespace changes
Inline
Side-by-side
Showing
25 changed files
with
658 additions
and
354 deletions
+658
-354
include/mysql_com.h
include/mysql_com.h
+6
-1
mysql-test/r/distinct.result
mysql-test/r/distinct.result
+2
-1
mysql-test/r/subselect.result
mysql-test/r/subselect.result
+19
-2
mysql-test/t/subselect.test
mysql-test/t/subselect.test
+10
-2
sql/item.cc
sql/item.cc
+18
-7
sql/item_cmpfunc.cc
sql/item_cmpfunc.cc
+2
-0
sql/item_subselect.cc
sql/item_subselect.cc
+144
-70
sql/item_subselect.h
sql/item_subselect.h
+89
-36
sql/mysql_priv.h
sql/mysql_priv.h
+4
-3
sql/mysqld.cc
sql/mysqld.cc
+2
-1
sql/net_pkg.cc
sql/net_pkg.cc
+4
-1
sql/net_serv.cc
sql/net_serv.cc
+24
-13
sql/sql_base.cc
sql/sql_base.cc
+20
-16
sql/sql_class.cc
sql/sql_class.cc
+28
-20
sql/sql_class.h
sql/sql_class.h
+2
-2
sql/sql_derived.cc
sql/sql_derived.cc
+1
-1
sql/sql_insert.cc
sql/sql_insert.cc
+2
-0
sql/sql_lex.cc
sql/sql_lex.cc
+7
-2
sql/sql_lex.h
sql/sql_lex.h
+30
-2
sql/sql_parse.cc
sql/sql_parse.cc
+11
-9
sql/sql_select.cc
sql/sql_select.cc
+33
-36
sql/sql_select.h
sql/sql_select.h
+3
-1
sql/sql_union.cc
sql/sql_union.cc
+188
-124
sql/sql_update.cc
sql/sql_update.cc
+3
-0
sql/sql_yacc.yy
sql/sql_yacc.yy
+6
-4
No files found.
include/mysql_com.h
View file @
b07aaeb2
...
...
@@ -132,8 +132,13 @@ typedef struct st_net {
unsigned
int
*
return_status
;
unsigned
char
reading_or_writing
;
char
save_char
;
my_bool
report_error
;
/* We should report error (we have unreported error) */
my_bool
no_send_ok
;
gptr
query_cache_query
;
/*
Pointer to query object in query cache, do not equal NULL (0) for
queries in cache that have not stored its results yet
*/
gptr
query_cache_query
;
}
NET
;
#define packet_error (~(unsigned long) 0)
...
...
mysql-test/r/distinct.result
View file @
b07aaeb2
...
...
@@ -92,7 +92,8 @@ NULL NULL NULL
0 0
select id >= 0 and id <= 5 as grp,count(*) from t1 group by grp;
grp count(*)
0 7
NULL 1
0 6
1 6
SELECT DISTINCT FACILITY FROM t1;
FACILITY
...
...
mysql-test/r/subselect.result
View file @
b07aaeb2
select (select 2);
(select 2)
2
drop table if exists t1,t2,t3,t4;
drop table if exists t1,t2,t3,t4
,t5
;
create table t1 (a int);
create table t2 (a int, b int);
create table t3 (a int);
...
...
@@ -82,4 +82,21 @@ select b,max(a) as ma from t4 group by b having b >= (select max(t2.a)
from t2 where t2.b=t4.b);
b ma
7 12
drop table t1,t2,t3,t4;
create table t5 (a int);
select (select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a), a from t2;
(select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a) a
NULL 1
2 2
insert into t5 values (5);
select (select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a), a from t2;
(select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a) a
NULL 1
2 2
insert into t5 values (2);
select (select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a), a from t2;
(select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a) a
NULL 1
2 2
select (select a from t1 where t1.a=t2.a union all select a from t5 where t5.a=t2.a), a from t2;
Subselect return more than 1 record
drop table t1,t2,t3,t4,t5;
mysql-test/t/subselect.test
View file @
b07aaeb2
select
(
select
2
);
drop
table
if
exists
t1
,
t2
,
t3
,
t4
;
drop
table
if
exists
t1
,
t2
,
t3
,
t4
,
t5
;
create
table
t1
(
a
int
);
create
table
t2
(
a
int
,
b
int
);
create
table
t3
(
a
int
);
...
...
@@ -33,4 +33,12 @@ select b,max(a) as ma from t4 group by b having b < (select max(t2.a)
from
t2
where
t2
.
b
=
t4
.
b
);
select
b
,
max
(
a
)
as
ma
from
t4
group
by
b
having
b
>=
(
select
max
(
t2
.
a
)
from
t2
where
t2
.
b
=
t4
.
b
);
drop
table
t1
,
t2
,
t3
,
t4
;
create
table
t5
(
a
int
);
select
(
select
a
from
t1
where
t1
.
a
=
t2
.
a
union
select
a
from
t5
where
t5
.
a
=
t2
.
a
),
a
from
t2
;
insert
into
t5
values
(
5
);
select
(
select
a
from
t1
where
t1
.
a
=
t2
.
a
union
select
a
from
t5
where
t5
.
a
=
t2
.
a
),
a
from
t2
;
insert
into
t5
values
(
2
);
select
(
select
a
from
t1
where
t1
.
a
=
t2
.
a
union
select
a
from
t5
where
t5
.
a
=
t2
.
a
),
a
from
t2
;
--
error
1230
select
(
select
a
from
t1
where
t1
.
a
=
t2
.
a
union
all
select
a
from
t5
where
t5
.
a
=
t2
.
a
),
a
from
t2
;
drop
table
t1
,
t2
,
t3
,
t4
,
t5
;
sql/item.cc
View file @
b07aaeb2
...
...
@@ -457,7 +457,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
if
(
!
field
)
// If field is not checked
{
Field
*
tmp
;
if
(
!
(
tmp
=
find_field_in_tables
(
thd
,
this
,
tables
)))
if
(
!
(
tmp
=
find_field_in_tables
(
thd
,
this
,
tables
,
0
)))
{
/*
We can't find table field in table list of current select,
...
...
@@ -473,9 +473,14 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
sl
&&
!
tmp
;
sl
=
sl
->
outer_select
())
tmp
=
find_field_in_tables
(
thd
,
this
,
(
TABLE_LIST
*
)(
last
=
sl
)
->
table_list
.
first
);
(
TABLE_LIST
*
)(
last
=
sl
)
->
table_list
.
first
,
0
);
if
(
!
tmp
)
return
1
;
{
// Call to produce appropriate error message
find_field_in_tables
(
thd
,
this
,
tables
,
1
);
return
-
1
;
}
else
{
depended_from
=
last
;
...
...
@@ -488,7 +493,8 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
s
=
s
->
outer_select
())
if
(
!
s
->
depended
)
{
s
->
depended
=
1
;
//Select is depended of outer select
// Select is depended of outer select
s
->
depended
=
s
->
master_unit
()
->
depended
=
1
;
//Tables will be reopened many times
for
(
TABLE_LIST
*
tbl
=
(
TABLE_LIST
*
)
s
->
table_list
.
first
;
...
...
@@ -803,7 +809,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
{
if
(
!
ref
)
{
if
(
!
(
ref
=
find_item_in_list
(
this
,
thd
->
lex
.
select
->
item_list
)))
if
(
!
(
ref
=
find_item_in_list
(
this
,
thd
->
lex
.
select
->
item_list
,
0
)))
{
/*
We can't find table field in table list of current select,
...
...
@@ -818,9 +824,13 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
for
(
SELECT_LEX
*
sl
=
thd
->
lex
.
select
->
outer_select
();
sl
&&
!
ref
;
sl
=
sl
->
outer_select
())
ref
=
find_item_in_list
(
this
,
(
last
=
sl
)
->
item_list
);
ref
=
find_item_in_list
(
this
,
(
last
=
sl
)
->
item_list
,
0
);
if
(
!
ref
)
{
// Call to report error
find_item_in_list
(
this
,
thd
->
lex
.
select
->
item_list
,
1
);
return
1
;
}
else
{
depended_from
=
last
;
...
...
@@ -833,7 +843,8 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
s
=
s
->
outer_select
())
if
(
!
s
->
depended
)
{
s
->
depended
=
1
;
//Select is depended of outer select
// Select is depended of outer select
s
->
depended
=
s
->
master_unit
()
->
depended
=
1
;
//Tables will be reopened many times
for
(
TABLE_LIST
*
tbl
=
(
TABLE_LIST
*
)
s
->
table_list
.
first
;
...
...
sql/item_cmpfunc.cc
View file @
b07aaeb2
...
...
@@ -1101,6 +1101,8 @@ Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
used_tables_cache
|=
item
->
used_tables
();
with_sum_func
=
with_sum_func
||
item
->
with_sum_func
;
const_item_cache
&=
item
->
const_item
();
if
(
item
->
maybe_null
)
maybe_null
=
1
;
}
if
(
thd
)
thd
->
cond_count
+=
list
.
elements
;
...
...
sql/item_subselect.cc
View file @
b07aaeb2
...
...
@@ -23,9 +23,6 @@ SUBSELECT TODO:
- remove double 'having' & 'having_list' from JOIN
(sql_select.h/sql_select.cc)
- subselect in HAVING clause
- add subselect union select (sql_union.cc)
*/
#ifdef __GNUC__
...
...
@@ -37,21 +34,17 @@ SUBSELECT TODO:
Item_subselect
::
Item_subselect
(
THD
*
thd
,
st_select_lex
*
select_lex
,
select_subselect
*
result
)
:
assigned
(
0
),
executed
(
0
),
optimized
(
0
),
error
(
0
)
engine_owner
(
1
),
value_assigned
(
0
)
{
DBUG_ENTER
(
"Item_subselect::Item_subselect"
);
DBUG_PRINT
(
"subs"
,
(
"select_lex 0x%xl"
,
(
long
)
select_lex
));
this
->
result
=
result
;
SELECT_LEX_UNIT
*
unit
=
select_lex
->
master_unit
();
unit
->
offset_limit_cnt
=
unit
->
global_parameters
->
offset_limit
;
unit
->
select_limit_cnt
=
unit
->
global_parameters
->
select_limit
+
unit
->
global_parameters
->
offset_limit
;
if
(
unit
->
select_limit_cnt
<
unit
->
global_parameters
->
select_limit
)
unit
->
select_limit_cnt
=
HA_POS_ERROR
;
// no limit
if
(
unit
->
select_limit_cnt
==
HA_POS_ERROR
)
select_lex
->
options
&=
~
OPTION_FOUND_ROWS
;
join
=
new
JOIN
(
thd
,
select_lex
->
item_list
,
select_lex
->
options
,
result
);
this
->
select_lex
=
select_lex
;
if
(
select_lex
->
next_select
())
engine
=
new
subselect_union_engine
(
thd
,
select_lex
->
master_unit
(),
result
,
this
);
else
engine
=
new
subselect_single_select_engine
(
thd
,
select_lex
,
result
,
this
);
assign_null
();
/*
item value is NULL if select_subselect not changed this value
...
...
@@ -61,6 +54,12 @@ Item_subselect::Item_subselect(THD *thd, st_select_lex *select_lex,
DBUG_VOID_RETURN
;
}
Item_subselect
::~
Item_subselect
()
{
if
(
engine_owner
)
delete
engine
;
}
void
Item_subselect
::
make_field
(
Send_field
*
tmp_field
)
{
if
(
null_value
)
...
...
@@ -78,62 +77,17 @@ void Item_subselect::make_field (Send_field *tmp_field)
bool
Item_subselect
::
fix_fields
(
THD
*
thd
,
TABLE_LIST
*
tables
,
Item
**
ref
)
{
// Is it one field subselect?
if
(
select_lex
->
item_list
.
elements
>
max_columns
)
if
(
engine
->
cols
()
>
max_columns
)
{
my_
printf_error
(
ER_SUBSELECT_NO_1_COL
,
ER
(
ER_SUBSELECT_NO_1_COL
),
MYF
(
0
));
my_
message
(
ER_SUBSELECT_NO_1_COL
,
ER
(
ER_SUBSELECT_NO_1_COL
),
MYF
(
0
));
return
1
;
}
SELECT_LEX
*
save_select
=
thd
->
lex
.
select
;
thd
->
lex
.
select
=
select_lex
;
if
(
join
->
prepare
((
TABLE_LIST
*
)
select_lex
->
table_list
.
first
,
select_lex
->
where
,
(
ORDER
*
)
select_lex
->
order_list
.
first
,
(
ORDER
*
)
select_lex
->
group_list
.
first
,
select_lex
->
having
,
(
ORDER
*
)
0
,
select_lex
,
select_lex
->
master_unit
()))
return
1
;
thd
->
lex
.
select
=
save_select
;
return
0
;
}
int
Item_subselect
::
exec
()
{
DBUG_ENTER
(
"Item_subselect::exec"
);
if
(
!
optimized
)
{
optimized
=
1
;
if
(
join
->
optimize
())
{
executed
=
1
;
DBUG_RETURN
(
join
->
error
?
join
->
error
:
1
);
}
}
if
(
join
->
select_lex
->
depended
&&
executed
)
{
if
(
join
->
reinit
())
{
error
=
1
;
DBUG_RETURN
(
1
);
}
assign_null
();
executed
=
assigned
=
0
;
}
if
(
!
executed
)
{
SELECT_LEX
*
save_select
=
join
->
thd
->
lex
.
select
;
join
->
thd
->
lex
.
select
=
select_lex
;
join
->
exec
();
join
->
thd
->
lex
.
select
=
save_select
;
executed
=
1
;
DBUG_RETURN
(
join
->
error
);
}
DBUG_RETURN
(
0
);
return
engine
->
prepare
();
}
inline
table_map
Item_subselect
::
used_tables
()
const
{
return
(
table_map
)
select_lex
->
depended
?
1L
:
0L
;
return
(
table_map
)
engine
->
depended
()
?
1L
:
0L
;
}
Item_singleval_subselect
::
Item_singleval_subselect
(
THD
*
thd
,
...
...
@@ -151,21 +105,21 @@ Item::Type Item_subselect::type() const
double
Item_singleval_subselect
::
val
()
{
if
(
exec
())
if
(
e
ngine
->
e
xec
())
return
0
;
return
real_value
;
}
longlong
Item_singleval_subselect
::
val_int
()
{
if
(
exec
())
if
(
e
ngine
->
e
xec
())
return
0
;
return
int_value
;
}
String
*
Item_singleval_subselect
::
val_str
(
String
*
str
)
{
if
(
exec
()
||
null_value
)
if
(
e
ngine
->
e
xec
()
||
null_value
)
return
0
;
return
&
str_value
;
}
...
...
@@ -183,23 +137,143 @@ Item_exists_subselect::Item_exists_subselect(THD *thd,
double
Item_exists_subselect
::
val
()
{
if
(
exec
())
if
(
e
ngine
->
e
xec
())
return
0
;
return
(
double
)
value
;
}
longlong
Item_exists_subselect
::
val_int
()
{
if
(
exec
())
if
(
e
ngine
->
e
xec
())
return
0
;
return
value
;
}
String
*
Item_exists_subselect
::
val_str
(
String
*
str
)
{
if
(
exec
())
if
(
e
ngine
->
e
xec
())
return
0
;
str
->
set
(
value
);
return
str
;
}
subselect_single_select_engine
::
subselect_single_select_engine
(
THD
*
thd
,
st_select_lex
*
select
,
select_subselect
*
result
,
Item_subselect
*
item
)
:
subselect_engine
(
thd
,
item
,
result
),
executed
(
0
),
optimized
(
0
)
{
select_lex
=
select
;
SELECT_LEX_UNIT
*
unit
=
select_lex
->
master_unit
();
unit
->
offset_limit_cnt
=
unit
->
global_parameters
->
offset_limit
;
unit
->
select_limit_cnt
=
unit
->
global_parameters
->
select_limit
+
unit
->
global_parameters
->
offset_limit
;
if
(
unit
->
select_limit_cnt
<
unit
->
global_parameters
->
select_limit
)
unit
->
select_limit_cnt
=
HA_POS_ERROR
;
// no limit
if
(
unit
->
select_limit_cnt
==
HA_POS_ERROR
)
select_lex
->
options
&=
~
OPTION_FOUND_ROWS
;
join
=
new
JOIN
(
thd
,
select_lex
->
item_list
,
select_lex
->
options
,
result
);
if
(
!
join
||
!
result
)
{
//out of memory
thd
->
fatal_error
=
1
;
my_message
(
ER_OUT_OF_RESOURCES
,
ER
(
ER_OUT_OF_RESOURCES
),
MYF
(
0
));
}
this
->
select_lex
=
select_lex
;
}
subselect_union_engine
::
subselect_union_engine
(
THD
*
thd
,
st_select_lex_unit
*
u
,
select_subselect
*
result
,
Item_subselect
*
item
)
:
subselect_engine
(
thd
,
item
,
result
)
{
unit
=
u
;
if
(
!
result
)
{
//out of memory
thd
->
fatal_error
=
1
;
my_message
(
ER_OUT_OF_RESOURCES
,
ER
(
ER_OUT_OF_RESOURCES
),
MYF
(
0
));
}
unit
->
item
=
item
;
}
int
subselect_single_select_engine
::
prepare
()
{
SELECT_LEX
*
save_select
=
thd
->
lex
.
select
;
thd
->
lex
.
select
=
select_lex
;
if
(
join
->
prepare
((
TABLE_LIST
*
)
select_lex
->
table_list
.
first
,
select_lex
->
where
,
(
ORDER
*
)
select_lex
->
order_list
.
first
,
(
ORDER
*
)
select_lex
->
group_list
.
first
,
select_lex
->
having
,
(
ORDER
*
)
0
,
select_lex
,
select_lex
->
master_unit
(),
0
))
return
1
;
thd
->
lex
.
select
=
save_select
;
return
0
;
}
int
subselect_union_engine
::
prepare
()
{
return
unit
->
prepare
(
thd
,
result
);
}
int
subselect_single_select_engine
::
exec
()
{
DBUG_ENTER
(
"subselect_single_select_engine::exec"
);
if
(
!
optimized
)
{
optimized
=
1
;
if
(
join
->
optimize
())
{
executed
=
1
;
DBUG_RETURN
(
join
->
error
?
join
->
error
:
1
);
}
}
if
(
select_lex
->
depended
&&
executed
)
{
if
(
join
->
reinit
())
DBUG_RETURN
(
1
);
item
->
assign_null
();
item
->
assigned
((
executed
=
0
));
}
if
(
!
executed
)
{
SELECT_LEX
*
save_select
=
join
->
thd
->
lex
.
select
;
join
->
thd
->
lex
.
select
=
select_lex
;
join
->
exec
();
join
->
thd
->
lex
.
select
=
save_select
;
executed
=
1
;
DBUG_RETURN
(
join
->
error
||
thd
->
fatal_error
);
}
DBUG_RETURN
(
0
);
}
int
subselect_union_engine
::
exec
()
{
return
unit
->
exec
();
}
uint
subselect_single_select_engine
::
cols
()
{
return
select_lex
->
item_list
.
elements
;
}
uint
subselect_union_engine
::
cols
()
{
return
unit
->
first_select
()
->
item_list
.
elements
;
}
bool
subselect_single_select_engine
::
depended
()
{
return
select_lex
->
depended
;
}
bool
subselect_union_engine
::
depended
()
{
return
unit
->
depended
;
}
sql/item_subselect.h
View file @
b07aaeb2
...
...
@@ -20,31 +20,25 @@
#pragma interface
/* gcc class implementation */
#endif
struct
st_select_lex
;
class
st_select_lex
;
class
st_select_lex_unit
;
class
JOIN
;
class
select_subselect
;
class
subselect_engine
;
/* base class for subselects */
class
Item_subselect
:
public
Item
{
my_bool
engine_owner
;
/* Is this item owner of engine */
my_bool
value_assigned
;
/* value already assigned to subselect */
protected:
/* engine that perform execution of subselect (single select or union) */
subselect_engine
*
engine
;
/* allowed number of columns (1 for single value subqueries) */
uint
max_columns
;
my_bool
assigned
;
/* value already assigned to subselect */
my_bool
executed
;
/* simple subselect is executed */
my_bool
optimized
;
/* simple subselect is optimized */
my_bool
error
;
/* error in query */
int
exec
();
virtual
void
assign_null
()
{
null_value
=
1
;
}
public:
st_select_lex
*
select_lex
;
JOIN
*
join
;
select_subselect
*
result
;
Item_subselect
(
THD
*
thd
,
st_select_lex
*
select_lex
,
select_subselect
*
result
);
Item_subselect
(
Item_subselect
*
item
)
...
...
@@ -52,14 +46,17 @@ public:
null_value
=
item
->
null_value
;
decimals
=
item
->
decimals
;
max_columns
=
item
->
max_columns
;
assigned
=
item
->
assigned
;
executed
=
item
->
executed
;
select_lex
=
item
->
select_lex
;
join
=
item
->
join
;
result
=
item
->
result
;
engine
=
item
->
engine
;
engine_owner
=
0
;
name
=
item
->
name
;
error
=
item
->
error
;
}
~
Item_subselect
();
virtual
void
assign_null
()
{
null_value
=
1
;
}
bool
assigned
()
{
return
value_assigned
;
}
void
assigned
(
bool
a
)
{
value_assigned
=
a
;
}
enum
Type
type
()
const
;
bool
is_null
()
{
return
null_value
;
}
void
make_field
(
Send_field
*
);
...
...
@@ -75,18 +72,10 @@ public:
class
Item_singleval_subselect
:
public
Item_subselect
{
protected:
longlong
int_value
;
double
real_value
;
enum
Item_result
res_type
;
longlong
int_value
;
/* here stored integer value of this item */
double
real_value
;
/* here stored real value of this item */
enum
Item_result
res_type
;
/* type of results */
virtual
void
assign_null
()
{
null_value
=
1
;
int_value
=
0
;
real_value
=
0
;
max_length
=
4
;
res_type
=
STRING_RESULT
;
}
public:
Item_singleval_subselect
(
THD
*
thd
,
st_select_lex
*
select_lex
);
Item_singleval_subselect
(
Item_singleval_subselect
*
item
)
:
...
...
@@ -98,6 +87,14 @@ public:
decimals
=
item
->
decimals
;
res_type
=
item
->
res_type
;
}
virtual
void
assign_null
()
{
null_value
=
1
;
int_value
=
0
;
real_value
=
0
;
max_length
=
4
;
res_type
=
STRING_RESULT
;
}
double
val
();
longlong
val_int
();
String
*
val_str
(
String
*
);
...
...
@@ -112,12 +109,8 @@ public:
class
Item_exists_subselect
:
public
Item_subselect
{
protected:
longlong
value
;
longlong
value
;
/* value of this item (boolean: exists/not-exists) */
virtual
void
assign_null
()
{
value
=
0
;
}
public:
Item_exists_subselect
(
THD
*
thd
,
st_select_lex
*
select_lex
);
Item_exists_subselect
(
Item_exists_subselect
*
item
)
:
...
...
@@ -125,6 +118,11 @@ public:
{
value
=
item
->
value
;
}
virtual
void
assign_null
()
{
value
=
0
;
}
Item
*
new_item
()
{
return
new
Item_exists_subselect
(
this
);
}
enum
Item_result
result_type
()
const
{
return
INT_RESULT
;}
longlong
val_int
();
...
...
@@ -133,3 +131,58 @@ public:
friend
class
select_exists_subselect
;
};
class
subselect_engine
{
protected:
select_subselect
*
result
;
/* results storage class */
THD
*
thd
;
/* pointer to current THD */
Item_subselect
*
item
;
/* item, that use this engine */
public:
static
void
*
operator
new
(
size_t
size
)
{
return
(
void
*
)
sql_alloc
((
uint
)
size
);
}
static
void
operator
delete
(
void
*
ptr
,
size_t
size
)
{}
subselect_engine
(
THD
*
thd
,
Item_subselect
*
si
,
select_subselect
*
res
)
{
result
=
res
;
item
=
si
;
this
->
thd
=
thd
;
}
virtual
int
prepare
()
=
0
;
virtual
int
exec
()
=
0
;
virtual
uint
cols
()
=
0
;
/* return number of columnss in select */
virtual
bool
depended
()
=
0
;
/* depended from outer select */
};
class
subselect_single_select_engine
:
public
subselect_engine
{
my_bool
executed
;
/* simple subselect is executed */
my_bool
optimized
;
/* simple subselect is optimized */
st_select_lex
*
select_lex
;
/* corresponding select_lex */
JOIN
*
join
;
/* corresponding JOIN structure */
public:
subselect_single_select_engine
(
THD
*
thd
,
st_select_lex
*
select
,
select_subselect
*
result
,
Item_subselect
*
item
);
virtual
int
prepare
();
virtual
int
exec
();
virtual
uint
cols
();
virtual
bool
depended
();
};
class
subselect_union_engine
:
public
subselect_engine
{
st_select_lex_unit
*
unit
;
/* corresponding unit structure */
public:
subselect_union_engine
(
THD
*
thd
,
st_select_lex_unit
*
u
,
select_subselect
*
result
,
Item_subselect
*
item
);
virtual
int
prepare
();
virtual
int
exec
();
virtual
uint
cols
();
virtual
bool
depended
();
};
sql/mysql_priv.h
View file @
b07aaeb2
...
...
@@ -373,7 +373,7 @@ int handle_select(THD *thd, LEX *lex, select_result *result);
int
mysql_select
(
THD
*
thd
,
TABLE_LIST
*
tables
,
List
<
Item
>
&
list
,
COND
*
conds
,
ORDER
*
order
,
ORDER
*
group
,
Item
*
having
,
ORDER
*
proc_param
,
ulong
select_type
,
select_result
*
result
,
SELECT_LEX_UNIT
*
unit
);
SELECT_LEX_UNIT
*
unit
,
bool
fake_select_lex
);
int
mysql_union
(
THD
*
thd
,
LEX
*
lex
,
select_result
*
result
);
int
mysql_derived
(
THD
*
thd
,
LEX
*
lex
,
SELECT_LEX_UNIT
*
s
,
TABLE_LIST
*
t
);
Field
*
create_tmp_field
(
THD
*
thd
,
TABLE
*
table
,
Item
*
item
,
Item
::
Type
type
,
...
...
@@ -438,7 +438,8 @@ bool wait_for_tables(THD *thd);
bool
table_is_used
(
TABLE
*
table
,
bool
wait_for_name_lock
);
bool
drop_locked_tables
(
THD
*
thd
,
const
char
*
db
,
const
char
*
table_name
);
void
abort_locked_tables
(
THD
*
thd
,
const
char
*
db
,
const
char
*
table_name
);
Field
*
find_field_in_tables
(
THD
*
thd
,
Item_field
*
item
,
TABLE_LIST
*
tables
);
Field
*
find_field_in_tables
(
THD
*
thd
,
Item_field
*
item
,
TABLE_LIST
*
tables
,
bool
report_error
);
Field
*
find_field_in_table
(
THD
*
thd
,
TABLE
*
table
,
const
char
*
name
,
uint
length
,
bool
check_grant
,
bool
allow_rowid
);
#ifdef HAVE_OPENSSL
...
...
@@ -526,7 +527,7 @@ TABLE *unlink_open_table(THD *thd,TABLE *list,TABLE *find);
SQL_SELECT
*
make_select
(
TABLE
*
head
,
table_map
const_tables
,
table_map
read_tables
,
COND
*
conds
,
int
*
error
);
Item
**
find_item_in_list
(
Item
*
item
,
List
<
Item
>
&
items
);
Item
**
find_item_in_list
(
Item
*
item
,
List
<
Item
>
&
items
,
bool
report_error
);
bool
insert_fields
(
THD
*
thd
,
TABLE_LIST
*
tables
,
const
char
*
db_name
,
const
char
*
table_name
,
List_iterator
<
Item
>
*
it
);
...
...
sql/mysqld.cc
View file @
b07aaeb2
...
...
@@ -1608,8 +1608,9 @@ static int my_message_sql(uint error, const char *str,
NET
*
net
;
DBUG_ENTER
(
"my_message_sql"
);
DBUG_PRINT
(
"error"
,(
"Message: '%s'"
,
str
));
if
((
net
=
my_pthread_getspecific_ptr
(
NET
*
,
THR_NET
)))
if
((
net
=
my_pthread_getspecific_ptr
(
NET
*
,
THR_NET
)))
{
net
->
report_error
=
1
;
if
(
!
net
->
last_error
[
0
])
// Return only first message
{
strmake
(
net
->
last_error
,
str
,
sizeof
(
net
->
last_error
)
-
1
);
...
...
sql/net_pkg.cc
View file @
b07aaeb2
...
...
@@ -72,7 +72,10 @@ void send_error(NET *net, uint sql_errno, const char *err)
}
VOID
(
net_write_command
(
net
,(
uchar
)
255
,(
char
*
)
err
,
length
));
if
(
thd
)
thd
->
fatal_error
=
0
;
// Error message is given
{
thd
->
fatal_error
=
0
;
// Error message is given
thd
->
net
.
report_error
=
0
;
}
DBUG_VOID_RETURN
;
}
...
...
sql/net_serv.cc
View file @
b07aaeb2
...
...
@@ -113,6 +113,7 @@ int my_net_init(NET *net, Vio* vio)
net
->
where_b
=
net
->
remain_in_buf
=
0
;
net
->
last_errno
=
0
;
net
->
query_cache_query
=
0
;
net
->
report_error
=
0
;
if
(
vio
!=
0
)
/* If real connection */
{
...
...
@@ -141,8 +142,9 @@ static my_bool net_realloc(NET *net, ulong length)
if
(
length
>=
max_allowed_packet
)
{
DBUG_PRINT
(
"error"
,(
"Packet too large (%lu)"
,
length
));
net
->
error
=
1
;
net
->
last_errno
=
ER_NET_PACKET_TOO_LARGE
;
net
->
error
=
1
;
net
->
report_error
=
1
;
net
->
last_errno
=
ER_NET_PACKET_TOO_LARGE
;
return
1
;
}
pkt_length
=
(
length
+
IO_SIZE
-
1
)
&
~
(
IO_SIZE
-
1
);
...
...
@@ -152,9 +154,10 @@ static my_bool net_realloc(NET *net, ulong length)
NET_HEADER_SIZE
+
COMP_HEADER_SIZE
,
MYF
(
MY_WME
))))
{
net
->
error
=
1
;
net
->
error
=
1
;
net
->
report_error
=
1
;
#ifdef MYSQL_SERVER
net
->
last_errno
=
ER_OUT_OF_RESOURCES
;
net
->
last_errno
=
ER_OUT_OF_RESOURCES
;
#endif
return
1
;
}
...
...
@@ -348,10 +351,12 @@ net_real_write(NET *net,const char *packet,ulong len)
COMP_HEADER_SIZE
,
MYF
(
MY_WME
))))
{
#ifdef MYSQL_SERVER
net
->
last_errno
=
ER_OUT_OF_RESOURCES
;
net
->
error
=
2
;
net
->
last_errno
=
ER_OUT_OF_RESOURCES
;
net
->
error
=
2
;
//TODO is it needed to set this variable if we have no socket
net
->
report_error
=
1
;
#endif
net
->
reading_or_writing
=
0
;
net
->
reading_or_writing
=
0
;
DBUG_RETURN
(
1
);
}
memcpy
(
b
+
header_length
,
packet
,
len
);
...
...
@@ -401,7 +406,8 @@ net_real_write(NET *net,const char *packet,ulong len)
"%s: my_net_write: fcntl returned error %d, aborting thread
\n
"
,
my_progname
,
vio_errno
(
net
->
vio
));
#endif
/* EXTRA_DEBUG */
net
->
error
=
2
;
/* Close socket */
net
->
error
=
2
;
/* Close socket */
net
->
report_error
=
1
;
goto
end
;
}
}
...
...
@@ -428,7 +434,8 @@ net_real_write(NET *net,const char *packet,ulong len)
continue
;
}
#endif
/* defined(THREAD_SAFE_CLIENT) && !defined(MYSQL_SERVER) */
net
->
error
=
2
;
/* Close socket */
net
->
error
=
2
;
/* Close socket */
net
->
report_error
=
1
;
#ifdef MYSQL_SERVER
net
->
last_errno
=
(
interrupted
?
ER_NET_WRITE_INTERRUPTED
:
ER_NET_ERROR_ON_WRITE
);
...
...
@@ -562,9 +569,10 @@ my_real_read(NET *net, ulong *complen)
my_progname
,
vio_errno
(
net
->
vio
));
#endif
/* EXTRA_DEBUG */
len
=
packet_error
;
net
->
error
=
2
;
/* Close socket */
net
->
error
=
2
;
/* Close socket */
net
->
report_error
=
1
;
#ifdef MYSQL_SERVER
net
->
last_errno
=
ER_NET_FCNTL_ERROR
;
net
->
last_errno
=
ER_NET_FCNTL_ERROR
;
#endif
goto
end
;
}
...
...
@@ -593,7 +601,8 @@ my_real_read(NET *net, ulong *complen)
#endif
DBUG_PRINT
(
"error"
,(
"Couldn't read packet: remain: %lu errno: %d length: %ld alarmed: %d"
,
remain
,
vio_errno
(
net
->
vio
),
length
,
alarmed
));
len
=
packet_error
;
net
->
error
=
2
;
/* Close socket */
net
->
error
=
2
;
/* Close socket */
net
->
report_error
=
1
;
#ifdef MYSQL_SERVER
net
->
last_errno
=
(
interrupted
?
ER_NET_READ_INTERRUPTED
:
ER_NET_READ_ERROR
);
...
...
@@ -622,6 +631,7 @@ my_real_read(NET *net, ulong *complen)
#endif
}
len
=
packet_error
;
net
->
report_error
=
1
;
#ifdef MYSQL_SERVER
net
->
last_errno
=
ER_NET_PACKETS_OUT_OF_ORDER
;
#endif
...
...
@@ -794,7 +804,8 @@ my_net_read(NET *net)
if
(
my_uncompress
((
byte
*
)
net
->
buff
+
net
->
where_b
,
&
packet_len
,
&
complen
))
{
net
->
error
=
2
;
/* caller will close socket */
net
->
error
=
2
;
/* caller will close socket */
net
->
report_error
=
1
;
#ifdef MYSQL_SERVER
net
->
last_errno
=
ER_NET_UNCOMPRESS_ERROR
;
#endif
...
...
sql/sql_base.cc
View file @
b07aaeb2
...
...
@@ -1711,7 +1711,8 @@ Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length,
Field
*
find_field_in_tables
(
THD
*
thd
,
Item_field
*
item
,
TABLE_LIST
*
tables
)
find_field_in_tables
(
THD
*
thd
,
Item_field
*
item
,
TABLE_LIST
*
tables
,
bool
report_error
)
{
Field
*
found
=
0
;
const
char
*
db
=
item
->
db_name
;
...
...
@@ -1748,7 +1749,7 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables)
}
if
(
found
)
return
found
;
if
(
!
found_table
)
if
(
!
found_table
&&
report_error
)
{
char
buff
[
NAME_LEN
*
2
+
1
];
if
(
db
)
...
...
@@ -1760,8 +1761,9 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables)
thd
->
where
);
}
else
my_printf_error
(
ER_BAD_FIELD_ERROR
,
ER
(
ER_BAD_FIELD_ERROR
),
MYF
(
0
),
item
->
full_name
(),
thd
->
where
);
if
(
report_error
)
my_printf_error
(
ER_BAD_FIELD_ERROR
,
ER
(
ER_BAD_FIELD_ERROR
),
MYF
(
0
),
item
->
full_name
(),
thd
->
where
);
return
(
Field
*
)
0
;
}
bool
allow_rowid
=
tables
&&
!
tables
->
next
;
// Only one table
...
...
@@ -1778,8 +1780,9 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables)
{
if
(
!
thd
->
where
)
// Returns first found
break
;
my_printf_error
(
ER_NON_UNIQ_ERROR
,
ER
(
ER_NON_UNIQ_ERROR
),
MYF
(
0
),
name
,
thd
->
where
);
if
(
report_error
)
my_printf_error
(
ER_NON_UNIQ_ERROR
,
ER
(
ER_NON_UNIQ_ERROR
),
MYF
(
0
),
name
,
thd
->
where
);
return
(
Field
*
)
0
;
}
found
=
field
;
...
...
@@ -1787,13 +1790,14 @@ find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables)
}
if
(
found
)
return
found
;
my_printf_error
(
ER_BAD_FIELD_ERROR
,
ER
(
ER_BAD_FIELD_ERROR
),
MYF
(
0
),
item
->
full_name
(),
thd
->
where
);
if
(
report_error
)
my_printf_error
(
ER_BAD_FIELD_ERROR
,
ER
(
ER_BAD_FIELD_ERROR
),
MYF
(
0
),
item
->
full_name
(),
thd
->
where
);
return
(
Field
*
)
0
;
}
Item
**
find_item_in_list
(
Item
*
find
,
List
<
Item
>
&
items
)
find_item_in_list
(
Item
*
find
,
List
<
Item
>
&
items
,
bool
report_error
)
{
List_iterator
<
Item
>
li
(
items
);
Item
**
found
=
0
,
*
item
;
...
...
@@ -1841,9 +1845,9 @@ find_item_in_list(Item *find,List<Item> &items)
break
;
}
}
if
(
!
found
&&
current_thd
->
where
)
my_printf_error
(
ER_BAD_FIELD_ERROR
,
ER
(
ER_BAD_FIELD_ERROR
),
MYF
(
0
),
find
->
full_name
(),
current_thd
->
where
);
if
(
!
found
&&
report_error
)
my_printf_error
(
ER_BAD_FIELD_ERROR
,
ER
(
ER_BAD_FIELD_ERROR
),
MYF
(
0
),
find
->
full_name
(),
current_thd
->
where
);
return
found
;
}
...
...
@@ -2303,8 +2307,8 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name,
int
setup_ftfuncs
(
THD
*
thd
)
{
List_iterator
<
Item_func_match
>
li
(
thd
->
lex
.
select
->
ftfunc_list
),
lj
(
thd
->
lex
.
select
->
ftfunc_list
);
List_iterator
<
Item_func_match
>
li
(
*
(
thd
->
lex
.
select
->
ftfunc_list
)
),
lj
(
*
(
thd
->
lex
.
select
->
ftfunc_list
)
);
Item_func_match
*
ftf
,
*
ftf2
;
while
((
ftf
=
li
++
))
...
...
@@ -2324,9 +2328,9 @@ int setup_ftfuncs(THD *thd)
int
init_ftfuncs
(
THD
*
thd
,
bool
no_order
)
{
if
(
thd
->
lex
.
select
->
ftfunc_list
.
elements
)
if
(
thd
->
lex
.
select
->
ftfunc_list
->
elements
)
{
List_iterator
<
Item_func_match
>
li
(
thd
->
lex
.
select
->
ftfunc_list
);
List_iterator
<
Item_func_match
>
li
(
*
(
thd
->
lex
.
select
->
ftfunc_list
)
);
Item_func_match
*
ifm
;
DBUG_PRINT
(
"info"
,(
"Performing FULLTEXT search"
));
thd
->
proc_info
=
"FULLTEXT initialization"
;
...
...
sql/sql_class.cc
View file @
b07aaeb2
...
...
@@ -407,13 +407,19 @@ bool select_send::send_data(List<Item> &items)
if
(
item
->
send
(
thd
,
packet
))
{
packet
->
free
();
// Free used
my_
error
(
ER_OUT_OF_RESOURCES
,
MYF
(
0
));
my_
message
(
ER_OUT_OF_RESOURCES
,
ER
(
ER_OUT_OF_RESOURCES
),
MYF
(
0
));
DBUG_RETURN
(
1
);
}
}
thd
->
sent_row_count
++
;
bool
error
=
my_net_write
(
&
thd
->
net
,(
char
*
)
packet
->
ptr
(),
packet
->
length
());
DBUG_RETURN
(
error
);
if
(
!
thd
->
net
.
report_error
)
{
DBUG_RETURN
(
my_net_write
(
&
thd
->
net
,
(
char
*
)
packet
->
ptr
(),
packet
->
length
()));
}
else
DBUG_RETURN
(
1
);
}
bool
select_send
::
send_eof
()
...
...
@@ -423,8 +429,13 @@ bool select_send::send_eof()
{
mysql_unlock_tables
(
thd
,
thd
->
lock
);
thd
->
lock
=
0
;
}
::
send_eof
(
&
thd
->
net
);
return
0
;
if
(
!
thd
->
net
.
report_error
)
{
::
send_eof
(
&
thd
->
net
);
return
0
;
}
else
return
1
;
}
...
...
@@ -460,7 +471,7 @@ select_export::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
option
);
if
(
!
access
(
path
,
F_OK
))
{
my_error
(
ER_FILE_EXISTS_ERROR
,
MYF
(
0
),
exchange
->
file_name
);
my_error
(
ER_FILE_EXISTS_ERROR
,
MYF
(
0
),
exchange
->
file_name
);
return
1
;
}
/* Create the file world readable */
...
...
@@ -646,9 +657,9 @@ err:
}
void
select_export
::
send_error
(
uint
errcode
,
const
char
*
err
)
void
select_export
::
send_error
(
uint
errcode
,
const
char
*
err
)
{
::
send_error
(
&
thd
->
net
,
errcode
,
err
)
;
my_message
(
errcode
,
err
,
MYF
(
0
));
;
(
void
)
end_io_cache
(
&
cache
);
(
void
)
my_close
(
file
,
MYF
(
0
));
file
=
-
1
;
...
...
@@ -660,9 +671,7 @@ bool select_export::send_eof()
int
error
=
test
(
end_io_cache
(
&
cache
));
if
(
my_close
(
file
,
MYF
(
MY_WME
)))
error
=
1
;
if
(
error
)
::
send_error
(
&
thd
->
net
);
else
if
(
!
error
)
::
send_ok
(
&
thd
->
net
,
row_count
);
file
=
-
1
;
return
error
;
...
...
@@ -735,7 +744,7 @@ bool select_dump::send_data(List<Item> &items)
}
if
(
row_count
++
>
1
)
{
my_error
(
ER_TOO_MANY_ROWS
,
MYF
(
0
));
my_error
(
ER_TOO_MANY_ROWS
,
MYF
(
0
));
goto
err
;
}
while
((
item
=
li
++
))
...
...
@@ -760,7 +769,7 @@ err:
void
select_dump
::
send_error
(
uint
errcode
,
const
char
*
err
)
{
::
send_error
(
&
thd
->
net
,
errcode
,
err
);
my_message
(
errcode
,
err
,
MYF
(
0
)
);
(
void
)
end_io_cache
(
&
cache
);
(
void
)
my_close
(
file
,
MYF
(
0
));
(
void
)
my_delete
(
path
,
MYF
(
0
));
// Delete file on error
...
...
@@ -772,9 +781,7 @@ bool select_dump::send_eof()
int
error
=
test
(
end_io_cache
(
&
cache
));
if
(
my_close
(
file
,
MYF
(
MY_WME
)))
error
=
1
;
if
(
error
)
::
send_error
(
&
thd
->
net
);
else
if
(
!
error
)
::
send_ok
(
&
thd
->
net
,
row_count
);
file
=
-
1
;
return
error
;
...
...
@@ -789,8 +796,9 @@ bool select_singleval_subselect::send_data(List<Item> &items)
{
DBUG_ENTER
(
"select_singleval_subselect::send_data"
);
Item_singleval_subselect
*
it
=
(
Item_singleval_subselect
*
)
item
;
if
(
it
->
assigned
){
my_printf_error
(
ER_SUBSELECT_NO_1_ROW
,
ER
(
ER_SUBSELECT_NO_1_ROW
),
MYF
(
0
));
if
(
it
->
assigned
()){
thd
->
fatal_error
=
1
;
my_message
(
ER_SUBSELECT_NO_1_ROW
,
ER
(
ER_SUBSELECT_NO_1_ROW
),
MYF
(
0
));
DBUG_RETURN
(
1
);
}
if
(
unit
->
offset_limit_cnt
)
...
...
@@ -816,7 +824,7 @@ bool select_singleval_subselect::send_data(List<Item> &items)
it
->
int_value
=
val_item
->
val_int
();
it
->
res_type
=
val_item
->
result_type
();
}
it
->
assigned
=
1
;
it
->
assigned
(
1
)
;
DBUG_RETURN
(
0
);
}
...
...
@@ -830,7 +838,7 @@ bool select_exists_subselect::send_data(List<Item> &items)
DBUG_RETURN
(
0
);
}
it
->
value
=
1
;
it
->
assigned
=
1
;
it
->
assigned
(
1
)
;
DBUG_RETURN
(
0
);
}
sql/sql_class.h
View file @
b07aaeb2
...
...
@@ -453,7 +453,7 @@ public:
bool
query_error
,
bootstrap
,
cleanup_done
;
bool
safe_to_cache_query
;
bool
volatile
killed
;
bool
prepare_command
;
bool
prepare_command
;
ulong
param_count
,
current_param_number
;
Error
<
mysql_st_error
>
err_list
;
Error
<
mysql_st_error
>
warn_list
;
...
...
@@ -621,7 +621,7 @@ public:
virtual
void
initialize_tables
(
JOIN
*
join
=
0
)
{}
virtual
void
send_error
(
uint
errcode
,
const
char
*
err
)
{
::
send_error
(
&
thd
->
net
,
errcode
,
err
);
my_message
(
errcode
,
err
,
MYF
(
0
)
);
}
virtual
bool
send_eof
()
=
0
;
virtual
void
abort
()
{}
...
...
sql/sql_derived.cc
View file @
b07aaeb2
...
...
@@ -99,7 +99,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
(
ORDER
*
)
sl
->
group_list
.
first
,
sl
->
having
,
(
ORDER
*
)
NULL
,
sl
->
options
|
thd
->
options
|
SELECT_NO_UNLOCK
,
derived_result
,
unit
);
derived_result
,
unit
,
0
);
if
(
!
res
)
{
// Here we entirely fix both TABLE_LIST and list of SELECT's as there were no derived tables
...
...
sql/sql_insert.cc
View file @
b07aaeb2
...
...
@@ -1331,6 +1331,7 @@ bool select_insert::send_data(List<Item> &values)
void
select_insert
::
send_error
(
uint
errcode
,
const
char
*
err
)
{
//TODO error should be sent at the query processing end
::
send_error
(
&
thd
->
net
,
errcode
,
err
);
table
->
file
->
extra
(
HA_EXTRA_NO_CACHE
);
table
->
file
->
activate_all_index
(
thd
);
...
...
@@ -1357,6 +1358,7 @@ bool select_insert::send_eof()
if
(
error
)
{
table
->
file
->
print_error
(
error
,
MYF
(
0
));
//TODO error should be sent at the query processing end
::
send_error
(
&
thd
->
net
);
return
1
;
}
...
...
sql/sql_lex.cc
View file @
b07aaeb2
...
...
@@ -146,7 +146,8 @@ LEX *lex_start(THD *thd, uchar *buf,uint length)
lex
->
length
=
0
;
lex
->
select
->
in_sum_expr
=
0
;
lex
->
select
->
expr_list
.
empty
();
lex
->
select
->
ftfunc_list
.
empty
();
lex
->
select
->
ftfunc_list_alloc
.
empty
();
lex
->
select
->
ftfunc_list
=
&
lex
->
select
->
ftfunc_list_alloc
;
lex
->
convert_set
=
(
lex
->
thd
=
thd
)
->
convert_set
;
lex
->
yacc_yyss
=
lex
->
yacc_yyvs
=
0
;
lex
->
ignore_space
=
test
(
thd
->
sql_mode
&
MODE_IGNORE_SPACE
);
...
...
@@ -918,6 +919,8 @@ void st_select_lex_unit::init_query()
global_parameters
=
this
;
select_limit_cnt
=
HA_POS_ERROR
;
offset_limit_cnt
=
0
;
optimized
=
0
;
item
=
0
;
}
void
st_select_lex
::
init_query
()
...
...
@@ -941,9 +944,11 @@ void st_select_lex::init_select()
expr_list
.
empty
();
interval_list
.
empty
();
use_index
.
empty
();
ftfunc_list
.
empty
();
ftfunc_list_alloc
.
empty
();
ftfunc_list
=
&
ftfunc_list_alloc
;
linkage
=
UNSPECIFIED_TYPE
;
depended
=
having_fix_field
=
0
;
}
/*
...
...
sql/sql_lex.h
View file @
b07aaeb2
...
...
@@ -216,7 +216,22 @@ private:
*/
class
st_lex
;
class
st_select_lex
;
class
THD
;
class
select_result
;
class
JOIN
;
class
select_union
;
class
st_select_lex_unit
:
public
st_select_lex_node
{
protected:
List
<
Item
>
item_list
;
List
<
JOIN
*>
joins
;
/* list of *JOINs, to delete it in cleanup() */
TABLE_LIST
result_table_list
;
select_union
*
union_result
;
TABLE
*
table
;
/* temporary table using for appending UNION results */
THD
*
thd
;
select_result
*
result
;
int
res
;
bool
describe
,
found_rows_for_union
,
optimized
;
// optimize phase already performed for UNION (unit)
public:
/*
Pointer to 'last' select or pointer to unit where stored
...
...
@@ -225,12 +240,21 @@ public:
st_select_lex_node
*
global_parameters
;
/* LIMIT clause runtime counters */
ha_rows
select_limit_cnt
,
offset_limit_cnt
;
bool
depended
;
/* depended from outer select subselect */
/* not NULL if union used in subselect, point to subselect item */
Item_subselect
*
item
;
void
init_query
();
bool
create_total_list
(
THD
*
thd
,
st_lex
*
lex
,
TABLE_LIST
**
result
);
st_select_lex
*
outer_select
()
{
return
(
st_select_lex
*
)
master
;
}
st_select_lex
*
first_select
()
{
return
(
st_select_lex
*
)
slave
;
}
st_select_lex_unit
*
next_unit
()
{
return
(
st_select_lex_unit
*
)
next
;
}
/* UNION methods */
int
prepare
(
THD
*
thd
,
select_result
*
result
);
int
exec
();
int
cleanup
();
friend
void
mysql_init_query
(
THD
*
thd
);
private:
bool
create_total_list_n_last_return
(
THD
*
thd
,
st_lex
*
lex
,
...
...
@@ -241,7 +265,6 @@ typedef struct st_select_lex_unit SELECT_LEX_UNIT;
/*
SELECT_LEX - store information of parsed SELECT_LEX statment
*/
class
JOIN
;
class
st_select_lex
:
public
st_select_lex_node
{
public:
char
*
db
,
*
db1
,
*
table1
,
*
db2
,
*
table2
;
/* For outer join using .. */
...
...
@@ -252,7 +275,12 @@ public:
List
<
Item
>
item_list
;
/* list of fields & expressions */
List
<
String
>
interval_list
,
use_index
,
*
use_index_ptr
,
ignore_index
,
*
ignore_index_ptr
;
List
<
Item_func_match
>
ftfunc_list
;
/*
Usualy it is pointer to ftfunc_list_alloc, but in union used to create fake
select_lex for calling mysql_select under results of union
*/
List
<
Item_func_match
>
*
ftfunc_list
;
List
<
Item_func_match
>
ftfunc_list_alloc
;
JOIN
*
join
;
/* after JOIN::prepare it is pointer to corresponding JOIN */
uint
in_sum_expr
;
bool
create_refs
,
...
...
sql/sql_parse.cc
View file @
b07aaeb2
...
...
@@ -665,7 +665,7 @@ pthread_handler_decl(handle_one_connection,arg)
if
(
thd
->
user_connect
)
decrease_user_connections
(
thd
->
user_connect
);
free_root
(
&
thd
->
mem_root
,
MYF
(
0
));
if
(
net
->
error
&&
net
->
vio
!=
0
)
if
(
net
->
error
&&
net
->
vio
!=
0
&&
net
->
report_error
)
{
if
(
!
thd
->
killed
&&
opt_warnings
)
sql_print_error
(
ER
(
ER_NEW_ABORTING_CONNECTION
),
...
...
@@ -1169,6 +1169,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break
;
}
case
COM_PING
:
DBUG_PRINT
(
"info"
,
(
"query: PING"
));
thread_safe_increment
(
com_other
,
&
LOCK_thread_count
);
send_ok
(
net
);
// Tell client we are alive
break
;
...
...
@@ -1257,6 +1258,7 @@ mysql_execute_command(void)
SELECT_LEX_UNIT
*
unit
=
&
lex
->
unit
;
DBUG_ENTER
(
"mysql_execute_command"
);
thd
->
net
.
report_error
=
0
;
if
(
thd
->
slave_thread
)
{
/*
...
...
@@ -1864,7 +1866,7 @@ mysql_execute_command(void)
(
ORDER
*
)
NULL
,
select_lex
->
options
|
thd
->
options
|
SELECT_NO_JOIN_CACHE
,
result
,
unit
);
result
,
unit
,
0
);
delete
result
;
}
else
...
...
@@ -2029,13 +2031,13 @@ mysql_execute_command(void)
lex
->
lock_option
,
table_count
)))
{
res
=
mysql_select
(
thd
,
tables
,
select_lex
->
item_list
,
select_lex
->
where
,
(
ORDER
*
)
NULL
,(
ORDER
*
)
NULL
,(
Item
*
)
NULL
,
(
ORDER
*
)
NULL
,
select_lex
->
options
|
thd
->
options
|
SELECT_NO_JOIN_CACHE
,
result
,
unit
);
res
=
mysql_select
(
thd
,
tables
,
select_lex
->
item_list
,
select_lex
->
where
,
(
ORDER
*
)
NULL
,(
ORDER
*
)
NULL
,(
Item
*
)
NULL
,
(
ORDER
*
)
NULL
,
select_lex
->
options
|
thd
->
options
|
SELECT_NO_JOIN_CACHE
,
result
,
unit
,
0
);
delete
result
;
}
else
...
...
sql/sql_select.cc
View file @
b07aaeb2
...
...
@@ -178,9 +178,14 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
select_lex
->
having
,
(
ORDER
*
)
lex
->
proc_list
.
first
,
select_lex
->
options
|
thd
->
options
,
result
,
&
(
lex
->
unit
));
result
,
&
(
lex
->
unit
)
,
0
);
if
(
res
&&
result
)
result
->
abort
();
if
(
res
||
thd
->
net
.
report_error
)
{
send_error
(
&
thd
->
net
,
0
,
MYF
(
0
));
res
=
1
;
}
delete
result
;
return
res
;
}
...
...
@@ -198,9 +203,10 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
*/
int
JOIN
::
prepare
(
TABLE_LIST
*
tables_init
,
COND
*
conds_init
,
ORDER
*
order_init
,
ORDER
*
group_init
,
Item
*
having_init
,
ORDER
*
proc_param_init
,
SELECT_LEX
*
select
,
SELECT_LEX_UNIT
*
unit
)
COND
*
conds_init
,
ORDER
*
order_init
,
ORDER
*
group_init
,
Item
*
having_init
,
ORDER
*
proc_param_init
,
SELECT_LEX
*
select
,
SELECT_LEX_UNIT
*
unit
,
bool
fake_select_lex
)
{
DBUG_ENTER
(
"JOIN::prepare"
);
...
...
@@ -211,7 +217,8 @@ JOIN::prepare(TABLE_LIST *tables_init,
proc_param
=
proc_param_init
;
tables_list
=
tables_init
;
select_lex
=
select
;
select
->
join
=
this
;
if
(
!
fake_select_lex
)
select
->
join
=
this
;
union_part
=
(
unit
->
first_select
()
->
next_select
()
!=
0
);
/* Check that all tables, fields, conds and order are ok */
...
...
@@ -231,7 +238,7 @@ JOIN::prepare(TABLE_LIST *tables_init,
select_lex
->
having_fix_field
=
1
;
bool
having_fix_rc
=
having
->
fix_fields
(
thd
,
tables_list
,
&
having
);
select_lex
->
having_fix_field
=
0
;
if
(
having_fix_rc
||
thd
->
fatal
_error
)
if
(
having_fix_rc
||
thd
->
net
.
report
_error
)
DBUG_RETURN
(
-
1
);
/* purecov: inspected */
if
(
having
->
with_sum_func
)
having
->
split_sum_func
(
all_fields
);
...
...
@@ -538,7 +545,7 @@ JOIN::optimize()
make_join_readinfo
(
this
,
(
select_options
&
(
SELECT_DESCRIBE
|
SELECT_NO_JOIN_CACHE
))
|
(
thd
->
lex
.
select
->
ftfunc_list
.
elements
?
(
thd
->
lex
.
select
->
ftfunc_list
->
elements
?
SELECT_NO_JOIN_CACHE
:
0
));
/* Need to tell Innobase that to play it safe, it should fetch all
...
...
@@ -650,16 +657,16 @@ JOIN::exec()
result
->
send_fields
(
fields_list
,
1
);
if
(
!
having
||
having
->
val_int
())
{
if
(
do_send_rows
&&
result
->
send_data
(
fields_list
))
{
result
->
send_error
(
0
,
NullS
);
/* purecov: inspected */
error
=
1
;
}
if
(
do_send_rows
&&
result
->
send_data
(
fields_list
))
{
result
->
send_error
(
0
,
NullS
);
/* purecov: inspected */
error
=
1
;
}
else
error
=
(
int
)
result
->
send_eof
();
}
else
error
=
(
int
)
result
->
send_eof
();
error
=
(
int
)
result
->
send_eof
();
}
delete
procedure
;
DBUG_VOID_RETURN
;
...
...
@@ -995,8 +1002,9 @@ JOIN::cleanup(THD *thd)
int
mysql_select
(
THD
*
thd
,
TABLE_LIST
*
tables
,
List
<
Item
>
&
fields
,
COND
*
conds
,
ORDER
*
order
,
ORDER
*
group
,
Item
*
having
,
ORDER
*
proc_param
,
ulong
select_options
,
select_result
*
result
,
SELECT_LEX_UNIT
*
unit
)
ORDER
*
order
,
ORDER
*
group
,
Item
*
having
,
ORDER
*
proc_param
,
ulong
select_options
,
select_result
*
result
,
SELECT_LEX_UNIT
*
unit
,
bool
fake_select_lex
)
{
JOIN
*
join
=
new
JOIN
(
thd
,
fields
,
select_options
,
result
);
...
...
@@ -1005,7 +1013,7 @@ mysql_select(THD *thd, TABLE_LIST *tables, List<Item> &fields, COND *conds,
thd
->
used_tables
=
0
;
// Updated by setup_fields
if
(
join
->
prepare
(
tables
,
conds
,
order
,
group
,
having
,
proc_param
,
&
(
thd
->
lex
.
select_lex
),
unit
))
&
(
thd
->
lex
.
select_lex
),
unit
,
fake_select_lex
))
{
DBUG_RETURN
(
-
1
);
}
...
...
@@ -1026,7 +1034,7 @@ err:
thd
->
limit_found_rows
=
join
->
send_records
;
thd
->
examined_row_count
=
join
->
examined_rows
;
thd
->
proc_info
=
"end"
;
int
error
=
join
->
cleanup
(
thd
)
;
int
error
=
(
fake_select_lex
?
0
:
join
->
cleanup
(
thd
))
||
thd
->
net
.
report_error
;
delete
join
;
DBUG_RETURN
(
error
);
}
...
...
@@ -1760,7 +1768,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
add_key_part
(
keyuse
,
field
);
}
if
(
thd
->
lex
.
select
->
ftfunc_list
.
elements
)
if
(
thd
->
lex
.
select
->
ftfunc_list
->
elements
)
{
add_ft_keys
(
keyuse
,
join_tab
,
cond
,
normal_tables
);
}
...
...
@@ -4329,7 +4337,7 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
VOID
(
table
->
file
->
extra
(
HA_EXTRA_WRITE_CACHE
));
empty_record
(
table
);
}
join
->
tmp_table
=
table
;
/* Save for easy recursion */
join
->
tmp_table
=
table
;
/* Save for easy recursion */
join
->
fields
=
fields
;
/* Set up select_end */
...
...
@@ -4379,20 +4387,14 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
}
else
{
error
=
sub_select
(
join
,
join_tab
,
0
);
error
=
sub_select
(
join
,
join_tab
,
0
);
if
(
error
>=
0
)
error
=
sub_select
(
join
,
join_tab
,
1
);
error
=
sub_select
(
join
,
join_tab
,
1
);
if
(
error
==
-
3
)
error
=
0
;
/* select_limit used */
error
=
0
;
/* select_limit used */
}
/* Return 1 if error is sent; -1 if error should be sent */
if
(
error
<
0
)
{
join
->
result
->
send_error
(
0
,
NullS
);
/* purecov: inspected */
error
=
1
;
// Error sent
}
else
if
(
error
>=
0
)
{
error
=
0
;
if
(
!
table
)
// If sending data to client
...
...
@@ -6445,10 +6447,7 @@ find_order_in_list(THD *thd,TABLE_LIST *tables,ORDER *order,List<Item> &fields,
order
->
in_field_list
=
1
;
return
0
;
}
const
char
*
save_where
=
thd
->
where
;
thd
->
where
=
0
;
// No error if not found
Item
**
item
=
find_item_in_list
(
*
order
->
item
,
fields
);
thd
->
where
=
save_where
;
Item
**
item
=
find_item_in_list
(
*
order
->
item
,
fields
,
0
);
if
(
item
)
{
order
->
item
=
item
;
// use it
...
...
@@ -6546,17 +6545,15 @@ setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields,
DBUG_ENTER
(
"setup_new_fields"
);
thd
->
set_query_id
=
1
;
// Not really needed, but...
thd
->
where
=
0
;
// Don't give error
for
(
;
new_field
;
new_field
=
new_field
->
next
)
{
if
((
item
=
find_item_in_list
(
*
new_field
->
item
,
fields
)))
if
((
item
=
find_item_in_list
(
*
new_field
->
item
,
fields
,
0
)))
new_field
->
item
=
item
;
/* Change to shared Item */
else
{
thd
->
where
=
"procedure list"
;
if
((
*
new_field
->
item
)
->
fix_fields
(
thd
,
tables
,
new_field
->
item
))
DBUG_RETURN
(
1
);
/* purecov: inspected */
thd
->
where
=
0
;
all_fields
.
push_front
(
*
new_field
->
item
);
new_field
->
item
=
all_fields
.
head_ref
();
}
...
...
sql/sql_select.h
View file @
b07aaeb2
...
...
@@ -209,6 +209,7 @@ class JOIN :public Sql_alloc{
send_records
(
0
),
found_records
(
0
),
examined_rows
(
0
),
thd
(
thd
),
sum_funcs
(
0
),
procedure
(
0
),
having
(
0
),
select_options
(
select_options
),
result
(
result
),
...
...
@@ -235,7 +236,8 @@ class JOIN :public Sql_alloc{
int
prepare
(
TABLE_LIST
*
tables
,
COND
*
conds
,
ORDER
*
order
,
ORDER
*
group
,
Item
*
having
,
ORDER
*
proc_param
,
SELECT_LEX
*
select
,
SELECT_LEX_UNIT
*
unit
);
ORDER
*
proc_param
,
SELECT_LEX
*
select
,
SELECT_LEX_UNIT
*
unit
,
bool
fake_select_lex
);
int
optimize
();
int
global_optimize
();
int
reinit
();
...
...
sql/sql_union.cc
View file @
b07aaeb2
...
...
@@ -24,31 +24,103 @@
#include "mysql_priv.h"
#include "sql_select.h"
int
mysql_union
(
THD
*
thd
,
LEX
*
lex
,
select_result
*
result
)
{
DBUG_ENTER
(
"mysql_union"
);
SELECT_LEX_UNIT
*
unit
=
&
lex
->
unit
;
int
res
=
0
;
if
(
!
(
res
=
unit
->
prepare
(
thd
,
result
)))
res
=
unit
->
exec
();
res
|=
unit
->
cleanup
();
DBUG_RETURN
(
res
);
}
/***************************************************************************
** store records in temporary table for UNION
***************************************************************************/
select_union
::
select_union
(
TABLE
*
table_par
)
:
table
(
table_par
)
{
bzero
((
char
*
)
&
info
,
sizeof
(
info
));
/*
We can always use DUP_IGNORE because the temporary table will only
contain a unique key if we are using not using UNION ALL
*/
info
.
handle_duplicates
=
DUP_IGNORE
;
}
select_union
::~
select_union
()
{
}
int
select_union
::
prepare
(
List
<
Item
>
&
list
,
SELECT_LEX_UNIT
*
u
)
{
unit
=
u
;
if
(
save_time_stamp
&&
list
.
elements
!=
table
->
fields
)
{
my_message
(
ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT
,
ER
(
ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT
),
MYF
(
0
));
return
-
1
;
}
return
0
;
}
bool
select_union
::
send_data
(
List
<
Item
>
&
values
)
{
if
(
unit
->
offset_limit_cnt
)
{
// using limit offset,count
unit
->
offset_limit_cnt
--
;
return
0
;
}
fill_record
(
table
->
field
,
values
);
if
((
write_record
(
table
,
&
info
)))
{
if
(
create_myisam_from_heap
(
table
,
tmp_table_param
,
info
.
errorno
,
0
))
return
1
;
}
return
0
;
}
bool
select_union
::
send_eof
()
{
return
0
;
}
int
mysql_union
(
THD
*
thd
,
LEX
*
lex
,
select_result
*
result
)
bool
select_union
::
flush
(
)
{
SELECT_LEX
*
sl
;
SELECT_LEX_UNIT
*
unit
=
&
(
lex
->
unit
);
List
<
Item
>
item_list
;
TABLE
*
table
;
int
describe
=
(
lex
->
select_lex
.
options
&
SELECT_DESCRIBE
)
?
1
:
0
;
int
res
;
bool
found_rows_for_union
=
false
;
TABLE_LIST
result_table_list
;
int
error
;
if
((
error
=
table
->
file
->
extra
(
HA_EXTRA_NO_CACHE
)))
{
table
->
file
->
print_error
(
error
,
MYF
(
0
));
::
send_error
(
&
thd
->
net
);
return
1
;
}
return
0
;
}
typedef
JOIN
*
JOIN_P
;
int
st_select_lex_unit
::
prepare
(
THD
*
thd
,
select_result
*
result
)
{
describe
=
(
first_select
()
->
options
&
SELECT_DESCRIBE
)
?
1
:
0
;
res
=
0
;
found_rows_for_union
=
false
;
TMP_TABLE_PARAM
tmp_table_param
;
select_union
*
union_result
;
DBUG_ENTER
(
"mysql_union"
)
;
st_select_lex_node
*
global
;
DBUG_ENTER
(
"st_select_lex_unit::prepare"
)
;
this
->
thd
=
thd
;
this
->
result
=
result
;
/* Global option */
if
(((
void
*
)(
global
=
unit
->
global_parameters
))
==
((
void
*
)
unit
))
if
(((
void
*
)(
global
_parameters
))
==
((
void
*
)
this
))
{
found_rows_for_union
=
lex
->
select_lex
.
options
&
OPTION_FOUND_ROWS
&&
!
describe
&&
global
->
select_limit
;
found_rows_for_union
=
first_select
()
->
options
&
OPTION_FOUND_ROWS
&&
!
describe
&&
global
_parameters
->
select_limit
;
if
(
found_rows_for_union
)
lex
->
select_lex
.
options
^=
OPTION_FOUND_ROWS
;
first_select
()
->
options
^=
OPTION_FOUND_ROWS
;
}
item_list
.
empty
();
if
(
describe
)
{
Item
*
item
;
...
...
@@ -70,8 +142,8 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
else
{
Item
*
item
;
List_iterator
<
Item
>
it
(
lex
->
select_lex
.
item_list
);
TABLE_LIST
*
first_table
=
(
TABLE_LIST
*
)
lex
->
select_lex
.
table_list
.
first
;
List_iterator
<
Item
>
it
(
first_select
()
->
item_list
);
TABLE_LIST
*
first_table
=
(
TABLE_LIST
*
)
first_select
()
->
table_list
.
first
;
/* Create a list of items that will be in the result set */
while
((
item
=
it
++
))
...
...
@@ -84,11 +156,12 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
bzero
((
char
*
)
&
tmp_table_param
,
sizeof
(
tmp_table_param
));
tmp_table_param
.
field_count
=
item_list
.
elements
;
if
(
!
(
table
=
create_tmp_table
(
thd
,
&
tmp_table_param
,
item_list
,
(
ORDER
*
)
0
,
!
describe
&
!
lex
->
union_option
,
(
ORDER
*
)
0
,
!
describe
&
!
thd
->
lex
.
union_option
,
1
,
0
,
(
lex
->
select_lex
.
options
|
thd
->
options
|
(
first_select
()
->
options
|
thd
->
options
|
TMP_TABLE_ALL_COLUMNS
),
unit
)))
this
)))
DBUG_RETURN
(
-
1
);
table
->
file
->
extra
(
HA_EXTRA_WRITE_CACHE
);
table
->
file
->
extra
(
HA_EXTRA_IGNORE_DUP_KEY
);
...
...
@@ -98,46 +171,82 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
result_table_list
.
table
=
table
;
if
(
!
(
union_result
=
new
select_union
(
table
)))
{
res
=
-
1
;
goto
exit
;
}
DBUG_RETURN
(
-
1
);
union_result
->
save_time_stamp
=!
describe
;
union_result
->
tmp_table_param
=&
tmp_table_param
;
for
(
sl
=
&
lex
->
select_lex
;
sl
;
sl
=
sl
->
next_select
())
// prepare selects
joins
.
empty
();
for
(
SELECT_LEX
*
sl
=
first_select
();
sl
;
sl
=
sl
->
next_select
())
{
lex
->
select
=
sl
;
unit
->
offset_limit_cnt
=
sl
->
offset_limit
;
unit
->
select_limit_cnt
=
sl
->
select_limit
+
sl
->
offset_limit
;
if
(
unit
->
select_limit_cnt
<
sl
->
select_limit
)
unit
->
select_limit_cnt
=
HA_POS_ERROR
;
// no limit
if
(
unit
->
select_limit_cnt
==
HA_POS_ERROR
)
JOIN
*
join
=
new
JOIN
(
thd
,
sl
->
item_list
,
sl
->
options
|
thd
->
options
|
SELECT_NO_UNLOCK
|
((
describe
)
?
SELECT_DESCRIBE
:
0
),
union_result
);
joins
.
push_back
(
new
JOIN_P
(
join
));
thd
->
lex
.
select
=
sl
;
offset_limit_cnt
=
sl
->
offset_limit
;
select_limit_cnt
=
sl
->
select_limit
+
sl
->
offset_limit
;
if
(
select_limit_cnt
<
sl
->
select_limit
)
select_limit_cnt
=
HA_POS_ERROR
;
// no limit
if
(
select_limit_cnt
==
HA_POS_ERROR
)
sl
->
options
&=
~
OPTION_FOUND_ROWS
;
res
=
mysql_select
(
thd
,
(
TABLE_LIST
*
)
sl
->
table_list
.
first
,
sl
->
item_list
,
sl
->
where
,
(
sl
->
braces
)
?
(
ORDER
*
)
sl
->
order_list
.
first
:
(
ORDER
*
)
0
,
(
ORDER
*
)
sl
->
group_list
.
first
,
sl
->
having
,
(
ORDER
*
)
NULL
,
sl
->
options
|
thd
->
options
|
SELECT_NO_UNLOCK
|
((
describe
)
?
SELECT_DESCRIBE
:
0
),
union_result
,
unit
);
if
(
res
)
goto
exit
;
res
=
join
->
prepare
((
TABLE_LIST
*
)
sl
->
table_list
.
first
,
sl
->
where
,
(
sl
->
braces
)
?
(
ORDER
*
)
sl
->
order_list
.
first
:
(
ORDER
*
)
0
,
(
ORDER
*
)
sl
->
group_list
.
first
,
sl
->
having
,
(
ORDER
*
)
NULL
,
sl
,
this
,
0
);
if
(
res
|
thd
->
fatal_error
)
DBUG_RETURN
(
res
|
thd
->
fatal_error
);
}
DBUG_RETURN
(
res
|
thd
->
fatal_error
);
}
int
st_select_lex_unit
::
exec
()
{
DBUG_ENTER
(
"st_select_lex_unit::exec"
);
if
(
depended
||
!
item
||
!
item
->
assigned
())
{
if
(
optimized
&&
item
&&
item
->
assigned
())
item
->
assigned
(
0
);
// We will reinit & rexecute unit
for
(
SELECT_LEX
*
sl
=
first_select
();
sl
;
sl
=
sl
->
next_select
())
{
thd
->
lex
.
select
=
sl
;
offset_limit_cnt
=
sl
->
offset_limit
;
select_limit_cnt
=
sl
->
select_limit
+
sl
->
offset_limit
;
if
(
select_limit_cnt
<
sl
->
select_limit
)
select_limit_cnt
=
HA_POS_ERROR
;
// no limit
if
(
select_limit_cnt
==
HA_POS_ERROR
)
sl
->
options
&=
~
OPTION_FOUND_ROWS
;
if
(
!
optimized
)
sl
->
join
->
optimize
();
else
sl
->
join
->
reinit
();
sl
->
join
->
exec
();
res
=
sl
->
join
->
error
;
if
(
res
)
DBUG_RETURN
(
res
);
}
optimized
=
1
;
}
if
(
union_result
->
flush
())
{
res
=
1
;
// Error is already sent
goto
exit
;
DBUG_RETURN
(
res
)
;
}
delete
union_result
;
/* Send result to 'result' */
lex
->
select
=
&
lex
->
select_lex
;
thd
->
lex
.
select
=
first_select
()
;
res
=-
1
;
{
/* Create a list of fields in the temporary table */
...
...
@@ -147,7 +256,9 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
List<Item_func_match> ftfunc_list;
ftfunc_list.empty();
#else
thd
->
lex
.
select_lex
.
ftfunc_list
.
empty
();
List
<
Item_func_match
>
empty_list
;
empty_list
.
empty
();
thd
->
lex
.
select_lex
.
ftfunc_list
=
&
empty_list
;
#endif
for
(
field
=
table
->
field
;
*
field
;
field
++
)
...
...
@@ -157,92 +268,45 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
}
if
(
!
thd
->
fatal_error
)
// Check if EOM
{
st_select_lex_node
*
global
=
unit
->
global_parameters
;
unit
->
offset_limit_cnt
=
global
->
offset_limit
;
unit
->
select_limit_cnt
=
global
->
select_limit
+
global
->
offset_limit
;
if
(
unit
->
select_limit_cnt
<
global
->
select_limit
)
unit
->
select_limit_cnt
=
HA_POS_ERROR
;
// no limit
if
(
unit
->
select_limit_cnt
==
HA_POS_ERROR
)
offset_limit_cnt
=
global_parameters
->
offset_limit
;
select_limit_cnt
=
global_parameters
->
select_limit
+
global_parameters
->
offset_limit
;
if
(
select_limit_cnt
<
global_parameters
->
select_limit
)
select_limit_cnt
=
HA_POS_ERROR
;
// no limit
if
(
select_limit_cnt
==
HA_POS_ERROR
)
thd
->
options
&=
~
OPTION_FOUND_ROWS
;
if
(
describe
)
unit
->
select_limit_cnt
=
HA_POS_ERROR
;
// no limit
select_limit_cnt
=
HA_POS_ERROR
;
// no limit
res
=
mysql_select
(
thd
,
&
result_table_list
,
item_list
,
NULL
,
(
describe
)
?
0
:
(
ORDER
*
)
global
->
order_list
.
first
,
(
describe
)
?
0
:
(
ORDER
*
)
global_parameters
->
order_list
.
first
,
(
ORDER
*
)
NULL
,
NULL
,
(
ORDER
*
)
NULL
,
thd
->
options
,
result
,
unit
);
thd
->
options
,
result
,
this
,
1
);
if
(
found_rows_for_union
&&
!
res
)
thd
->
limit_found_rows
=
(
ulonglong
)
table
->
file
->
records
;
}
}
exit:
free_tmp_table
(
thd
,
table
);
thd
->
lex
.
select_lex
.
ftfunc_list
=
&
thd
->
lex
.
select_lex
.
ftfunc_list_alloc
;
DBUG_RETURN
(
res
);
}
/***************************************************************************
** store records in temporary table for UNION
***************************************************************************/
select_union
::
select_union
(
TABLE
*
table_par
)
:
table
(
table_par
)
int
st_select_lex_unit
::
cleanup
()
{
bzero
((
char
*
)
&
info
,
sizeof
(
info
));
/*
We can always use DUP_IGNORE because the temporary table will only
contain a unique key if we are using not using UNION ALL
*/
info
.
handle_duplicates
=
DUP_IGNORE
;
}
select_union
::~
select_union
()
{
}
int
select_union
::
prepare
(
List
<
Item
>
&
list
,
SELECT_LEX_UNIT
*
u
)
{
unit
=
u
;
if
(
save_time_stamp
&&
list
.
elements
!=
table
->
fields
)
{
my_message
(
ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT
,
ER
(
ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT
),
MYF
(
0
));
return
-
1
;
}
return
0
;
}
bool
select_union
::
send_data
(
List
<
Item
>
&
values
)
{
if
(
unit
->
offset_limit_cnt
)
{
// using limit offset,count
unit
->
offset_limit_cnt
--
;
return
0
;
}
fill_record
(
table
->
field
,
values
);
if
((
write_record
(
table
,
&
info
)))
{
if
(
create_myisam_from_heap
(
table
,
tmp_table_param
,
info
.
errorno
,
0
))
return
1
;
}
return
0
;
}
bool
select_union
::
send_eof
()
{
return
0
;
}
bool
select_union
::
flush
()
{
int
error
;
if
((
error
=
table
->
file
->
extra
(
HA_EXTRA_NO_CACHE
)))
DBUG_ENTER
(
"st_select_lex_unit::cleanup"
);
delete
union_result
;
free_tmp_table
(
thd
,
table
);
table
=
0
;
// Safety
List_iterator
<
JOIN
*>
j
(
joins
);
JOIN
**
join
;
while
((
join
=
j
++
))
{
table
->
file
->
print_error
(
error
,
MYF
(
0
)
);
::
send_error
(
&
thd
->
net
)
;
return
1
;
(
*
join
)
->
cleanup
(
thd
);
delete
*
join
;
delete
join
;
}
return
0
;
joins
.
empty
();
DBUG_RETURN
(
0
);
}
sql/sql_update.cc
View file @
b07aaeb2
...
...
@@ -642,6 +642,8 @@ bool multi_update::send_data(List<Item> &values)
void
multi_update
::
send_error
(
uint
errcode
,
const
char
*
err
)
{
//TODO error should be sent at the query processing end
/* First send error what ever it is ... */
::
send_error
(
&
thd
->
net
,
errcode
,
err
);
...
...
@@ -766,6 +768,7 @@ bool multi_update::send_eof()
if
(
error
==
-
1
)
error
=
0
;
thd
->
proc_info
=
"end"
;
//TODO error should be sent at the query processing end
if
(
error
)
send_error
(
error
,
"An error occured in multi-table update"
);
...
...
sql/sql_yacc.yy
View file @
b07aaeb2
...
...
@@ -1763,10 +1763,10 @@ simple_expr:
| singleval_subselect { $$= $1; }
| '{' ident expr '}' { $$= $3; }
| MATCH ident_list_arg AGAINST '(' expr ')'
{ Select->ftfunc_list
.
push_back((Item_func_match *)
{ Select->ftfunc_list
->
push_back((Item_func_match *)
($$=new Item_func_match_nl(*$2,$5))); }
| MATCH ident_list_arg AGAINST '(' expr IN_SYM BOOLEAN_SYM MODE_SYM ')'
{ Select->ftfunc_list
.
push_back((Item_func_match *)
{ Select->ftfunc_list
->
push_back((Item_func_match *)
($$=new Item_func_match_bool(*$2,$5))); }
| BINARY expr %prec NEG { $$= new Item_func_binary($2); }
| CAST_SYM '(' expr AS cast_type ')' { $$= create_func_cast($3, $5); }
...
...
@@ -3999,7 +3999,8 @@ singleval_subselect:
singleval_subselect_init:
select_init
{
$$= new Item_singleval_subselect(current_thd, Lex->select);
$$= new Item_singleval_subselect(current_thd,
Lex->select->master_unit()->first_select());
};
exists_subselect:
...
...
@@ -4012,7 +4013,8 @@ exists_subselect:
exists_subselect_init:
select_init
{
$$= new Item_exists_subselect(current_thd, Lex->select);
$$= new Item_exists_subselect(current_thd,
Lex->select->master_unit()->first_select());
};
subselect_start:
...
...
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