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
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
906903b9
Commit
906903b9
authored
May 09, 2002
by
bell@sanja.is.com.ua
Browse files
Options
Browse Files
Download
Plain Diff
merge
parents
7167b59a
ead6f225
Changes
17
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
558 additions
and
281 deletions
+558
-281
mysql-test/r/union.result
mysql-test/r/union.result
+0
-1
sql/item_sum.cc
sql/item_sum.cc
+5
-3
sql/mysql_priv.h
sql/mysql_priv.h
+5
-4
sql/sql_class.cc
sql/sql_class.cc
+11
-8
sql/sql_class.h
sql/sql_class.h
+29
-15
sql/sql_delete.cc
sql/sql_delete.cc
+2
-1
sql/sql_derived.cc
sql/sql_derived.cc
+22
-17
sql/sql_insert.cc
sql/sql_insert.cc
+8
-6
sql/sql_lex.cc
sql/sql_lex.cc
+117
-0
sql/sql_lex.h
sql/sql_lex.h
+133
-16
sql/sql_parse.cc
sql/sql_parse.cc
+75
-68
sql/sql_select.cc
sql/sql_select.cc
+50
-43
sql/sql_select.h
sql/sql_select.h
+4
-1
sql/sql_union.cc
sql/sql_union.cc
+53
-71
sql/sql_update.cc
sql/sql_update.cc
+9
-4
sql/sql_yacc.yy
sql/sql_yacc.yy
+27
-15
sql/table.h
sql/table.h
+8
-8
No files found.
mysql-test/r/union.result
View file @
906903b9
...
...
@@ -88,7 +88,6 @@ explain (select a,b from t1 limit 2) union all (select a,b from t2 order by a l
table type possible_keys key key_len ref rows Extra
t1 ALL NULL NULL NULL NULL 4
t2 ALL NULL NULL NULL NULL 4 Using filesort
t1 ALL NULL NULL NULL NULL 4
(select sql_calc_found_rows a,b from t1 limit 2) union all (select a,b from t2 order by a) limit 2;
a b
1 a
...
...
sql/item_sum.cc
View file @
906903b9
...
...
@@ -940,6 +940,7 @@ bool Item_sum_count_distinct::fix_fields(THD *thd,TABLE_LIST *tables)
bool
Item_sum_count_distinct
::
setup
(
THD
*
thd
)
{
List
<
Item
>
list
;
SELECT_LEX
*
select_lex
=
current_lex
->
select
;
/* Create a table with an unique key over all parameters */
for
(
uint
i
=
0
;
i
<
arg_count
;
i
++
)
{
...
...
@@ -961,9 +962,10 @@ bool Item_sum_count_distinct::setup(THD *thd)
free_tmp_table
(
thd
,
table
);
tmp_table_param
->
cleanup
();
}
if
(
!
(
table
=
create_tmp_table
(
thd
,
tmp_table_param
,
list
,
(
ORDER
*
)
0
,
1
,
0
,
0
,
current_lex
->
select
->
options
|
thd
->
options
)))
if
(
!
(
table
=
create_tmp_table
(
thd
,
tmp_table_param
,
list
,
(
ORDER
*
)
0
,
1
,
0
,
0
,
select_lex
->
options
|
thd
->
options
,
(
SELECT_LEX_UNIT
*
)
select_lex
->
master
)))
return
1
;
table
->
file
->
extra
(
HA_EXTRA_NO_ROWS
);
// Don't update rows
table
->
no_rows
=
1
;
...
...
sql/mysql_priv.h
View file @
906903b9
...
...
@@ -291,7 +291,7 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list);
bool
mysql_change_db
(
THD
*
thd
,
const
char
*
name
);
void
mysql_parse
(
THD
*
thd
,
char
*
inBuf
,
uint
length
);
void
mysql_init_select
(
LEX
*
lex
);
bool
mysql_new_select
(
LEX
*
lex
);
bool
mysql_new_select
(
LEX
*
lex
,
bool
move_down
);
void
mysql_init_multi_delete
(
LEX
*
lex
);
void
init_max_user_conn
(
void
);
void
free_max_user_conn
(
void
);
...
...
@@ -359,9 +359,10 @@ int setup_order(THD *thd,TABLE_LIST *tables, List<Item> &fields,
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
);
int
mysql_union
(
THD
*
thd
,
LEX
*
lex
,
select_result
*
result
);
int
mysql_derived
(
THD
*
thd
,
LEX
*
lex
,
SELECT_LEX
*
s
,
TABLE_LIST
*
t
);
ulong
select_type
,
select_result
*
result
,
SELECT_LEX_UNIT
*
unit
);
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
,
Item_result_field
***
copy_func
,
Field
**
from_field
,
bool
group
,
bool
modify_item
);
...
...
sql/sql_class.cc
View file @
906903b9
...
...
@@ -389,9 +389,9 @@ bool select_send::send_data(List<Item> &items)
String
*
packet
=
&
thd
->
packet
;
DBUG_ENTER
(
"send_data"
);
if
(
thd
->
offset_limi
t
)
if
(
unit
->
offset_limit_cn
t
)
{
// using limit offset,count
thd
->
offset_limi
t
--
;
unit
->
offset_limit_cn
t
--
;
DBUG_RETURN
(
0
);
}
packet
->
length
(
0
);
// Reset packet
...
...
@@ -439,11 +439,12 @@ select_export::~select_export()
}
int
select_export
::
prepare
(
List
<
Item
>
&
list
)
select_export
::
prepare
(
List
<
Item
>
&
list
,
SELECT_LEX_UNIT
*
u
)
{
char
path
[
FN_REFLEN
];
uint
option
=
4
;
bool
blob_flag
=
0
;
unit
=
u
;
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
option
|=
1
;
// Force use of db directory
#endif
...
...
@@ -510,9 +511,9 @@ bool select_export::send_data(List<Item> &items)
String
tmp
(
buff
,
sizeof
(
buff
)),
*
res
;
tmp
.
length
(
0
);
if
(
thd
->
offset_limi
t
)
if
(
unit
->
offset_limit_cn
t
)
{
// using limit offset,count
thd
->
offset_limi
t
--
;
unit
->
offset_limit_cn
t
--
;
DBUG_RETURN
(
0
);
}
row_count
++
;
...
...
@@ -678,9 +679,11 @@ select_dump::~select_dump()
}
int
select_dump
::
prepare
(
List
<
Item
>
&
list
__attribute__
((
unused
)))
select_dump
::
prepare
(
List
<
Item
>
&
list
__attribute__
((
unused
)),
SELECT_LEX_UNIT
*
u
)
{
uint
option
=
4
;
unit
=
u
;
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
option
|=
1
;
// Force use of db directory
#endif
...
...
@@ -719,9 +722,9 @@ bool select_dump::send_data(List<Item> &items)
Item
*
item
;
DBUG_ENTER
(
"send_data"
);
if
(
thd
->
offset_limi
t
)
if
(
unit
->
offset_limit_cn
t
)
{
// using limit offset,count
thd
->
offset_limi
t
--
;
unit
->
offset_limit_cn
t
--
;
DBUG_RETURN
(
0
);
}
if
(
row_count
++
>
1
)
...
...
sql/sql_class.h
View file @
906903b9
...
...
@@ -382,7 +382,7 @@ class THD :public ilink {
#endif
ulonglong
next_insert_id
,
last_insert_id
,
current_insert_id
,
limit_found_rows
;
ha_rows
select_limit
,
offset_limit
,
default_select_limit
,
cuted_fields
,
ha_rows
default_select_limit
,
cuted_fields
,
max_join_size
,
sent_row_count
,
examined_row_count
;
table_map
used_tables
;
UC
*
user_connect
;
...
...
@@ -551,10 +551,15 @@ void send_error(NET *net,uint sql_errno=0, const char *err=0);
class
select_result
:
public
Sql_alloc
{
protected:
THD
*
thd
;
SELECT_LEX_UNIT
*
unit
;
public:
select_result
();
virtual
~
select_result
()
{};
virtual
int
prepare
(
List
<
Item
>
&
list
)
{
return
0
;
}
virtual
int
prepare
(
List
<
Item
>
&
list
,
SELECT_LEX_UNIT
*
u
)
{
unit
=
u
;
return
0
;
}
virtual
bool
send_fields
(
List
<
Item
>
&
list
,
uint
flag
)
=
0
;
virtual
bool
send_data
(
List
<
Item
>
&
items
)
=
0
;
virtual
void
initialize_tables
(
JOIN
*
join
=
0
)
{}
...
...
@@ -587,7 +592,7 @@ class select_export :public select_result {
public:
select_export
(
sql_exchange
*
ex
)
:
exchange
(
ex
),
file
(
-
1
),
row_count
(
0L
)
{}
~
select_export
();
int
prepare
(
List
<
Item
>
&
list
);
int
prepare
(
List
<
Item
>
&
list
,
SELECT_LEX_UNIT
*
u
);
bool
send_fields
(
List
<
Item
>
&
list
,
uint
flag
)
{
return
0
;
}
bool
send_data
(
List
<
Item
>
&
items
);
...
...
@@ -606,7 +611,7 @@ class select_dump :public select_result {
select_dump
(
sql_exchange
*
ex
)
:
exchange
(
ex
),
file
(
-
1
),
row_count
(
0L
)
{
path
[
0
]
=
0
;
}
~
select_dump
();
int
prepare
(
List
<
Item
>
&
list
);
int
prepare
(
List
<
Item
>
&
list
,
SELECT_LEX_UNIT
*
u
);
bool
send_fields
(
List
<
Item
>
&
list
,
uint
flag
)
{
return
0
;
}
bool
send_data
(
List
<
Item
>
&
items
);
...
...
@@ -629,7 +634,7 @@ class select_insert :public select_result {
info
.
handle_duplicates
=
duplic
;
}
~
select_insert
();
int
prepare
(
List
<
Item
>
&
list
);
int
prepare
(
List
<
Item
>
&
list
,
SELECT_LEX_UNIT
*
u
);
bool
send_fields
(
List
<
Item
>
&
list
,
uint
flag
)
{
return
0
;
}
bool
send_data
(
List
<
Item
>
&
items
);
...
...
@@ -658,7 +663,7 @@ class select_create: public select_insert {
create_info
(
create_info_par
),
lock
(
0
)
{}
int
prepare
(
List
<
Item
>
&
list
);
int
prepare
(
List
<
Item
>
&
list
,
SELECT_LEX_UNIT
*
u
);
bool
send_data
(
List
<
Item
>
&
values
);
bool
send_eof
();
void
abort
();
...
...
@@ -672,7 +677,7 @@ class select_union :public select_result {
select_union
(
TABLE
*
table_par
);
~
select_union
();
int
prepare
(
List
<
Item
>
&
list
);
int
prepare
(
List
<
Item
>
&
list
,
SELECT_LEX_UNIT
*
u
);
bool
send_fields
(
List
<
Item
>
&
list
,
uint
flag
)
{
return
0
;
}
bool
send_data
(
List
<
Item
>
&
items
);
...
...
@@ -706,19 +711,28 @@ class Table_ident :public Sql_alloc {
public:
LEX_STRING
db
;
LEX_STRING
table
;
SELECT_LEX
*
sel
;
inline
Table_ident
(
LEX_STRING
db_arg
,
LEX_STRING
table_arg
,
bool
force
)
:
table
(
table_arg
),
sel
((
SELECT_LEX
*
)
0
)
SELECT_LEX
_UNIT
*
sel
;
inline
Table_ident
(
LEX_STRING
db_arg
,
LEX_STRING
table_arg
,
bool
force
)
:
table
(
table_arg
),
sel
((
SELECT_LEX
_UNIT
*
)
0
)
{
if
(
!
force
&&
(
current_thd
->
client_capabilities
&
CLIENT_NO_SCHEMA
))
db
.
str
=
0
;
else
db
=
db_arg
;
}
inline
Table_ident
(
LEX_STRING
table_arg
)
:
table
(
table_arg
),
sel
((
SELECT_LEX
*
)
0
)
{
db
.
str
=
0
;}
inline
Table_ident
(
SELECT_LEX
*
s
)
:
sel
(
s
)
{
db
.
str
=
0
;
table
.
str
=
(
char
*
)
""
;
table
.
length
=
0
;}
inline
Table_ident
(
LEX_STRING
table_arg
)
:
table
(
table_arg
),
sel
((
SELECT_LEX_UNIT
*
)
0
)
{
db
.
str
=
0
;
}
inline
Table_ident
(
SELECT_LEX_UNIT
*
s
)
:
sel
(
s
)
{
db
.
str
=
0
;
table
.
str
=
(
char
*
)
""
;
table
.
length
=
0
;
}
inline
void
change_db
(
char
*
db_name
)
{
db
.
str
=
db_name
;
db
.
length
=
(
uint
)
strlen
(
db_name
);
}
{
db
.
str
=
db_name
;
db
.
length
=
(
uint
)
strlen
(
db_name
);
}
};
// this is needed for user_vars hash
...
...
@@ -778,7 +792,7 @@ class Unique :public Sql_alloc
multi_delete
(
THD
*
thd
,
TABLE_LIST
*
dt
,
thr_lock_type
lock_option_arg
,
uint
num_of_tables
);
~
multi_delete
();
int
prepare
(
List
<
Item
>
&
list
);
int
prepare
(
List
<
Item
>
&
list
,
SELECT_LEX_UNIT
*
u
);
bool
send_fields
(
List
<
Item
>
&
list
,
uint
flag
)
{
return
0
;
}
bool
send_data
(
List
<
Item
>
&
items
);
...
...
@@ -807,7 +821,7 @@ class Unique :public Sql_alloc
enum
enum_duplicates
handle_duplicates
,
thr_lock_type
lock_option_arg
,
uint
num
);
~
multi_update
();
int
prepare
(
List
<
Item
>
&
list
);
int
prepare
(
List
<
Item
>
&
list
,
SELECT_LEX_UNIT
*
u
);
bool
send_fields
(
List
<
Item
>
&
list
,
uint
flag
)
{
return
0
;
}
bool
send_data
(
List
<
Item
>
&
items
);
...
...
sql/sql_delete.cc
View file @
906903b9
...
...
@@ -232,9 +232,10 @@ multi_delete::multi_delete(THD *thd_arg, TABLE_LIST *dt,
int
multi_delete
::
prepare
(
List
<
Item
>
&
values
)
multi_delete
::
prepare
(
List
<
Item
>
&
values
,
SELECT_LEX_UNIT
*
u
)
{
DBUG_ENTER
(
"multi_delete::prepare"
);
unit
=
u
;
do_delete
=
true
;
thd
->
proc_info
=
"deleting from main table"
;
...
...
sql/sql_derived.cc
View file @
906903b9
...
...
@@ -28,21 +28,25 @@
static
const
char
*
any_db
=
"*any*"
;
// Special symbol for check_access
int
mysql_derived
(
THD
*
thd
,
LEX
*
lex
,
SELECT_LEX
*
s
,
TABLE_LIST
*
t
)
int
mysql_derived
(
THD
*
thd
,
LEX
*
lex
,
SELECT_LEX_UNIT
*
unit
,
TABLE_LIST
*
t
)
{
SELECT_LEX
*
sl
=
s
;
/*
TODO: make derived tables with union inside (now only 1 SELECT may be
procesed)
*/
SELECT_LEX
*
sl
=
(
SELECT_LEX
*
)
unit
->
slave
;
List
<
Item
>
item_list
;
TABLE
*
table
;
int
res
;
select_union
*
derived_result
;
TABLE_LIST
*
tables
=
(
TABLE_LIST
*
)
sl
->
table_list
.
first
;
TABLE_LIST
*
tables
=
(
TABLE_LIST
*
)
sl
->
table_list
.
first
;
TMP_TABLE_PARAM
tmp_table_param
;
DBUG_ENTER
(
"mysql_derived"
);
if
(
tables
)
res
=
check_table_access
(
thd
,
SELECT_ACL
,
tables
);
res
=
check_table_access
(
thd
,
SELECT_ACL
,
tables
);
else
res
=
check_access
(
thd
,
SELECT_ACL
,
any_db
);
res
=
check_access
(
thd
,
SELECT_ACL
,
any_db
);
if
(
res
)
DBUG_RETURN
(
-
1
);
...
...
@@ -52,7 +56,7 @@ int mysql_derived(THD *thd, LEX *lex,SELECT_LEX *s, TABLE_LIST *t)
{
if
(
cursor
->
derived
)
{
res
=
mysql_derived
(
thd
,
lex
,(
SELECT_LEX
*
)
cursor
->
derived
,
cursor
);
res
=
mysql_derived
(
thd
,
lex
,
(
SELECT_LEX_UNIT
*
)
cursor
->
derived
,
cursor
);
if
(
res
)
DBUG_RETURN
(
res
);
}
}
...
...
@@ -71,9 +75,11 @@ int mysql_derived(THD *thd, LEX *lex,SELECT_LEX *s, TABLE_LIST *t)
}
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
,
sl
->
item_list
,
(
ORDER
*
)
0
,
0
,
1
,
0
,
(
sl
->
options
|
thd
->
options
|
TMP_TABLE_ALL_COLUMNS
))))
if
(
!
(
table
=
create_tmp_table
(
thd
,
&
tmp_table_param
,
sl
->
item_list
,
(
ORDER
*
)
0
,
0
,
1
,
0
,
(
sl
->
options
|
thd
->
options
|
TMP_TABLE_ALL_COLUMNS
),
unit
)))
{
res
=-
1
;
goto
exit
;
...
...
@@ -81,11 +87,11 @@ int mysql_derived(THD *thd, LEX *lex,SELECT_LEX *s, TABLE_LIST *t)
if
((
derived_result
=
new
select_union
(
table
)))
{
thd
->
offset_limit
=
sl
->
offset_limit
;
thd
->
select_limit
=
sl
->
select_limit
+
sl
->
offset_limit
;
if
(
thd
->
select_limi
t
<
sl
->
select_limit
)
thd
->
select_limi
t
=
HA_POS_ERROR
;
if
(
thd
->
select_limi
t
==
HA_POS_ERROR
)
unit
->
offset_limit_cnt
=
sl
->
offset_limit
;
unit
->
select_limit_cnt
=
sl
->
select_limit
+
sl
->
offset_limit
;
if
(
unit
->
select_limit_cn
t
<
sl
->
select_limit
)
unit
->
select_limit_cn
t
=
HA_POS_ERROR
;
if
(
unit
->
select_limit_cn
t
==
HA_POS_ERROR
)
sl
->
options
&=
~
OPTION_FOUND_ROWS
;
res
=
mysql_select
(
thd
,
tables
,
sl
->
item_list
,
...
...
@@ -93,7 +99,7 @@ int mysql_derived(THD *thd, LEX *lex,SELECT_LEX *s, TABLE_LIST *t)
(
ORDER
*
)
sl
->
group_list
.
first
,
sl
->
having
,
(
ORDER
*
)
NULL
,
sl
->
options
|
thd
->
options
|
SELECT_NO_UNLOCK
,
derived_result
);
derived_result
,
unit
);
if
(
!
res
)
{
// Here we entirely fix both TABLE_LIST and list of SELECT's as there were no derived tables
...
...
@@ -103,9 +109,8 @@ int mysql_derived(THD *thd, LEX *lex,SELECT_LEX *s, TABLE_LIST *t)
{
t
->
real_name
=
table
->
real_name
;
t
->
table
=
table
;
sl
->
prev
->
next
=
sl
->
next
;
sl
->
exclude
()
;
t
->
derived
=
(
SELECT_LEX
*
)
0
;
// just in case ...
if
(
!
sl
->
next
)
lex
->
last_select
=
sl
;
}
}
delete
derived_result
;
...
...
sql/sql_insert.cc
View file @
906903b9
...
...
@@ -1266,10 +1266,11 @@ bool delayed_insert::handle_inserts(void)
***************************************************************************/
int
select_insert
::
prepare
(
List
<
Item
>
&
values
)
select_insert
::
prepare
(
List
<
Item
>
&
values
,
SELECT_LEX_UNIT
*
u
)
{
DBUG_ENTER
(
"select_insert::prepare"
);
unit
=
u
;
save_time_stamp
=
table
->
time_stamp
;
if
(
check_insert_fields
(
thd
,
table
,
*
fields
,
values
,
1
))
DBUG_RETURN
(
1
);
...
...
@@ -1302,9 +1303,9 @@ select_insert::~select_insert()
bool
select_insert
::
send_data
(
List
<
Item
>
&
values
)
{
if
(
thd
->
offset_limi
t
)
if
(
unit
->
offset_limit_cn
t
)
{
// using limit offset,count
thd
->
offset_limi
t
--
;
unit
->
offset_limit_cn
t
--
;
return
0
;
}
if
(
fields
->
elements
)
...
...
@@ -1380,10 +1381,11 @@ bool select_insert::send_eof()
***************************************************************************/
int
select_create
::
prepare
(
List
<
Item
>
&
values
)
select_create
::
prepare
(
List
<
Item
>
&
values
,
SELECT_LEX_UNIT
*
u
)
{
DBUG_ENTER
(
"select_create::prepare"
);
unit
=
u
;
table
=
create_table_from_items
(
thd
,
create_info
,
db
,
name
,
extra_fields
,
keys
,
&
values
,
&
lock
);
if
(
!
table
)
...
...
@@ -1413,9 +1415,9 @@ select_create::prepare(List<Item> &values)
bool
select_create
::
send_data
(
List
<
Item
>
&
values
)
{
if
(
thd
->
offset_limi
t
)
if
(
unit
->
offset_limit_cn
t
)
{
// using limit offset,count
thd
->
offset_limi
t
--
;
unit
->
offset_limit_cn
t
--
;
return
0
;
}
fill_record
(
field
,
values
);
...
...
sql/sql_lex.cc
View file @
906903b9
...
...
@@ -879,3 +879,120 @@ int yylex(void *arg)
}
}
}
/*
st_select_lex structures initialisations
*/
void
st_select_lex_node
::
init_query
()
{
next
=
master
=
slave
=
link_next
=
0
;
prev
=
link_prev
=
0
;
}
void
st_select_lex_node
::
init_select
()
{
order_list
.
elements
=
0
;
order_list
.
first
=
0
;
order_list
.
next
=
(
byte
**
)
&
order_list
.
first
;
select_limit
=
HA_POS_ERROR
;
offset_limit
=
0
;
}
void
st_select_lex_unit
::
init_query
()
{
st_select_lex_node
::
init_query
();
global_parameters
=
this
;
select_limit_cnt
=
HA_POS_ERROR
;
offset_limit_cnt
=
0
;
}
void
st_select_lex
::
init_query
()
{
st_select_lex_node
::
init_query
();
table_list
.
elements
=
0
;
table_list
.
first
=
0
;
table_list
.
next
=
(
byte
**
)
&
table_list
.
first
;
item_list
.
empty
();
}
void
st_select_lex
::
init_select
()
{
st_select_lex_node
::
init_select
();
group_list
.
elements
=
0
;
group_list
.
first
=
0
;
group_list
.
next
=
(
byte
**
)
&
group_list
.
first
;
options
=
0
;
where
=
having
=
0
;
when_list
.
empty
();
expr_list
.
empty
();
interval_list
.
empty
();
use_index
.
empty
();
ftfunc_list
.
empty
();
linkage
=
UNSPECIFIED_TYPE
;
}
/*
st_select_lex structures linking
*/
/* include on level down */
void
st_select_lex_node
::
include_down
(
st_select_lex_node
*
upper
)
{
if
((
next
=
upper
->
slave
))
next
->
prev
=
&
next
;
prev
=
&
upper
->
slave
;
upper
->
slave
=
this
;
master
=
upper
;
}
/* include neighbour (on same level) */
void
st_select_lex_node
::
include_neighbour
(
st_select_lex_node
*
before
)
{
if
((
next
=
before
->
next
))
next
->
prev
=
&
next
;
prev
=
&
before
->
next
;
before
->
next
=
this
;
master
=
before
->
master
;
}
/* including in global SELECT_LEX list */
void
st_select_lex_node
::
include_global
(
st_select_lex_node
**
plink
)
{
if
((
link_next
=
*
plink
))
link_next
->
link_prev
=
&
link_next
;
link_prev
=
plink
;
*
plink
=
this
;
}
//excluding from global list (internal function)
void
st_select_lex_node
::
fast_exclude
()
{
if
(
link_prev
)
{
if
((
*
link_prev
=
link_next
))
link_next
->
link_prev
=
link_prev
;
// Remove slave structure
for
(;
slave
;
slave
=
slave
->
next
)
slave
->
fast_exclude
();
}
}
/*
excluding select_lex structure (except first (first select can't be
deleted, because it is most upper select))
*/
void
st_select_lex_node
::
exclude
()
{
//exclude from global list
fast_exclude
();
//exclude from other structures
if
((
*
prev
=
next
))
next
->
prev
=
prev
;
/*
We do not need following statements, because prev pointer of first
list element point to master->slave
if (master->slave == this)
master->slave= next;
*/
}
sql/sql_lex.h
View file @
906903b9
...
...
@@ -103,28 +103,143 @@ typedef struct st_lex_master_info
}
LEX_MASTER_INFO
;
enum
sub_select_type
{
UNSPECIFIED_TYPE
,
UNION_TYPE
,
INTERSECT_TYPE
,
EXCEPT_TYPE
,
NOT_A_SELECT
,
DERIVED_TABLE_TYPE
};
enum
sub_select_type
{
UNSPECIFIED_TYPE
,
UNION_TYPE
,
INTERSECT_TYPE
,
EXCEPT_TYPE
,
GLOBAL_OPTIONS_TYPE
,
DERIVED_TABLE_TYPE
};
/* The state of the lex parsing for selects */
/*
The state of the lex parsing for selects
All select describing structures linked with following pointers:
- list of neighbors (next/prev) (prev of first element point to slave
pointer of upper structure)
- one level units for unit (union) structure
- member of one union(unit) for ordinary select_lex
- pointer to master
- outer select_lex for unit (union)
- unit structure for ordinary select_lex
- pointer to slave
- first list element of select_lex belonged to this unit for unit
- first unit in list of units that belong to this select_lex (as
subselects or derived tables) for ordinary select_lex
- list of all select_lex (for group operation like correcting list of opened
tables)
for example for following query:
typedef
struct
st_select_lex
{
select *
from table1
where table1.field IN (select * from table1_1_1 union
select * from table1_1_2)
union
select *
from table2
where table2.field=(select (select f1 from table2_1_1_1_1
where table2_1_1_1_1.f2=table2_1_1.f3)
from table2_1_1
where table2_1_1.f1=table2.f2)
union
select * from table3;
we will have following structure:
main unit
select1 select2 select3
|^^ |^
s||| ||master
l||| |+---------------------------------+
a||| +---------------------------------+|
v|||master slave ||
e||+-------------------------+ ||
V| neighbor | V|
unit 1.1<==================>unit1.2 unit2.1
select1.1.1 select 1.1.2 select1.2.1 select2.1.1 select2.1.2
|^
||
V|
unit2.1.1.1
select2.1.1.1.1
relation in main unit will be following:
main unit
|^^^
||||
|||+------------------------------+
||+--------------+ |
slave||master | |
V| neighbor | neighbor |
select1<========>select2<========>select3
list of all select_lex will be following (as it will be constructed by
parser):
select1->select2->select3->select2.1.1->select 2.1.2->select2.1.1.1.1-+
|
+---------------------------------------------------------------------+
|
+->select1.1.1->select1.1.2
*/
/*
Base class for st_select_lex (SELECT_LEX) &
st_select_lex_unit (SELECT_LEX_UNIT)
*/
struct
st_select_lex_node
{
enum
sub_select_type
linkage
;
char
*
db
,
*
db1
,
*
table1
,
*
db2
,
*
table2
;
/* For outer join using .. */
Item
*
where
,
*
having
;
ha_rows
select_limit
,
offset_limit
;
st_select_lex_node
*
next
,
**
prev
,
/* neighbor list */
*
master
,
*
slave
,
/* vertical links */
*
link_next
,
**
link_prev
;
/* list of whole SELECT_LEX */
SQL_LIST
order_list
;
/* ORDER clause */
ha_rows
select_limit
,
offset_limit
;
/* LIMIT clause parameters */
void
init_query
();
void
init_select
();
void
include_down
(
st_select_lex_node
*
upper
);
void
include_neighbour
(
st_select_lex_node
*
before
);
void
include_global
(
st_select_lex_node
**
plink
);
void
exclude
();
private:
void
fast_exclude
();
};
/*
SELECT_LEX_UNIT - unit of selects (UNION, INTERSECT, ...) group
SELECT_LEXs
*/
struct
st_select_lex_unit
:
public
st_select_lex_node
{
/*
Pointer to 'last' select or pointer to unit where stored
global parameters for union
*/
st_select_lex_node
*
global_parameters
;
/* LIMIT clause runtime counters */
ha_rows
select_limit_cnt
,
offset_limit_cnt
;
void
init_query
();
};
typedef
struct
st_select_lex_unit
SELECT_LEX_UNIT
;
/*
SELECT_LEX - store information of parsed SELECT_LEX statment
*/
struct
st_select_lex
:
public
st_select_lex_node
{
char
*
db
,
*
db1
,
*
table1
,
*
db2
,
*
table2
;
/* For outer join using .. */
Item
*
where
,
*
having
;
/* WHERE & HAVING clauses */
ulong
options
;
List
<
List_item
>
expr_list
;
List
<
List_item
>
when_list
;
SQL_LIST
order_list
,
table_list
,
group_list
;
List
<
Item
>
item_list
;
List
<
String
>
interval_list
,
use_index
,
*
use_index_ptr
,
List
<
List_item
>
when_list
;
/* WHEN clause */
SQL_LIST
table_list
,
group_list
;
/* FROM & GROUP BY clauses */
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
;
uint
in_sum_expr
,
sort_default
;
bool
create_refs
,
braces
;
st_select_lex
*
next
,
*
prev
;
}
SELECT_LEX
;
bool
create_refs
,
braces
;
/* SELECT ... UNION (SELECT ... ) <- this braces */
void
init_query
();
void
init_select
();
};
typedef
struct
st_select_lex
SELECT_LEX
;
class
Set_option
:
public
Sql_alloc
{
public:
...
...
@@ -137,13 +252,15 @@ class Set_option :public Sql_alloc {
:
name
(
par_name
),
item
(
par_item
),
name_length
(
length
),
type
(
par_type
)
{}
};
/* The state of the lex parsing. This is saved in the THD struct */
typedef
struct
st_lex
{
uint
yylineno
,
yytoklen
;
/* Simulate lex */
LEX_YYSTYPE
yylval
;
SELECT_LEX
select_lex
,
*
select
,
*
last_select
;
SELECT_LEX_UNIT
unit
;
/* most upper unit */
SELECT_LEX
select_lex
,
/* first SELECT_LEX */
/* current SELECT_LEX in parsing */
*
select
;
uchar
*
ptr
,
*
tok_start
,
*
tok_end
,
*
end_of_query
;
char
*
length
,
*
dec
,
*
change
,
*
name
;
char
*
backup_dir
;
/* For RESTORE/BACKUP */
...
...
sql/sql_parse.cc
View file @
906903b9
...
...
@@ -1203,11 +1203,12 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
void
mysql_execute_command
(
void
)
{
int
res
=
0
;
THD
*
thd
=
current_thd
;
int
res
=
0
;
THD
*
thd
=
current_thd
;
LEX
*
lex
=
&
thd
->
lex
;
TABLE_LIST
*
tables
=
(
TABLE_LIST
*
)
lex
->
select_lex
.
table_list
.
first
;
SELECT_LEX
*
select_lex
=
lex
->
select
;
TABLE_LIST
*
tables
=
(
TABLE_LIST
*
)
lex
->
select_lex
.
table_list
.
first
;
SELECT_LEX
*
select_lex
=
lex
->
select
;
SELECT_LEX_UNIT
*
unit
=
&
lex
->
unit
;
DBUG_ENTER
(
"mysql_execute_command"
);
if
(
thd
->
slave_thread
)
...
...
@@ -1240,8 +1241,10 @@ mysql_execute_command(void)
{
for
(
TABLE_LIST
*
cursor
=
tables
;
cursor
;
cursor
=
cursor
->
next
)
if
(
cursor
->
derived
&&
mysql_derived
(
thd
,
lex
,(
SELECT_LEX
*
)
cursor
->
derived
,
cursor
))
cursor
=
cursor
->
next
)
if
(
cursor
->
derived
&&
mysql_derived
(
thd
,
lex
,
(
SELECT_LEX_UNIT
*
)
cursor
->
derived
,
cursor
))
DBUG_VOID_RETURN
;
}
if
((
lex
->
select_lex
.
next
&&
create_total_list
(
thd
,
lex
,
&
tables
))
||
...
...
@@ -1272,11 +1275,11 @@ mysql_execute_command(void)
break
;
// Error message is given
}
thd
->
offset_limit
=
select_lex
->
offset_limit
;
thd
->
select_limit
=
select_lex
->
select_limit
+
select_lex
->
offset_limit
;
if
(
thd
->
select_limi
t
<
select_lex
->
select_limit
)
thd
->
select_limi
t
=
HA_POS_ERROR
;
// no limit
if
(
thd
->
select_limi
t
==
HA_POS_ERROR
)
unit
->
offset_limit_cnt
=
select_lex
->
offset_limit
;
unit
->
select_limit_cnt
=
select_lex
->
select_limit
+
select_lex
->
offset_limit
;
if
(
unit
->
select_limit_cn
t
<
select_lex
->
select_limit
)
unit
->
select_limit_cn
t
=
HA_POS_ERROR
;
// no limit
if
(
unit
->
select_limit_cn
t
==
HA_POS_ERROR
)
select_lex
->
options
&=
~
OPTION_FOUND_ROWS
;
if
(
lex
->
exchange
)
...
...
@@ -1501,10 +1504,11 @@ mysql_execute_command(void)
for
(
table
=
tables
->
next
;
table
;
table
=
table
->
next
)
table
->
lock_type
=
lex
->
lock_option
;
}
thd
->
offset_limit
=
select_lex
->
offset_limit
;
thd
->
select_limit
=
select_lex
->
select_limit
+
select_lex
->
offset_limit
;
if
(
thd
->
select_limit
<
select_lex
->
select_limit
)
thd
->
select_limit
=
HA_POS_ERROR
;
// No limit
unit
->
offset_limit_cnt
=
select_lex
->
offset_limit
;
unit
->
select_limit_cnt
=
select_lex
->
select_limit
+
select_lex
->
offset_limit
;
if
(
unit
->
select_limit_cnt
<
select_lex
->
select_limit
)
unit
->
select_limit_cnt
=
HA_POS_ERROR
;
// No limit
/* Skip first table, which is the table we are creating */
lex
->
select_lex
.
table_list
.
first
=
...
...
@@ -1786,13 +1790,13 @@ mysql_execute_command(void)
while
((
item
=
value_list
++
))
total_list
.
push_back
(
item
);
res
=
mysql_select
(
thd
,
tables
,
total_list
,
select_lex
->
where
,
(
ORDER
*
)
NULL
,(
ORDER
*
)
NULL
,
(
Item
*
)
NULL
,
(
ORDER
*
)
NULL
,
select_lex
->
options
|
thd
->
options
|
SELECT_NO_JOIN_CACHE
,
resul
t
);
res
=
mysql_select
(
thd
,
tables
,
total_list
,
select_lex
->
where
,
(
ORDER
*
)
NULL
,
(
ORDER
*
)
NULL
,
(
Item
*
)
NULL
,
(
ORDER
*
)
NULL
,
select_lex
->
options
|
thd
->
options
|
SELECT_NO_JOIN_CACHE
,
result
,
uni
t
);
delete
result
;
}
else
...
...
@@ -1842,10 +1846,10 @@ mysql_execute_command(void)
}
select_result
*
result
;
thd
->
offset_limit
=
select_lex
->
offset_limit
;
thd
->
select_limit
=
select_lex
->
select_limit
+
select_lex
->
offset_limit
;
if
(
thd
->
select_limi
t
<
select_lex
->
select_limit
)
thd
->
select_limi
t
=
HA_POS_ERROR
;
// No limit
unit
->
offset_limit_cnt
=
select_lex
->
offset_limit
;
unit
->
select_limit_cnt
=
select_lex
->
select_limit
+
select_lex
->
offset_limit
;
if
(
unit
->
select_limit_cn
t
<
select_lex
->
select_limit
)
unit
->
select_limit_cn
t
=
HA_POS_ERROR
;
// No limit
if
(
check_dup
(
tables
->
db
,
tables
->
real_name
,
tables
->
next
))
{
...
...
@@ -1961,7 +1965,7 @@ mysql_execute_command(void)
(
ORDER
*
)
NULL
,
select_lex
->
options
|
thd
->
options
|
SELECT_NO_JOIN_CACHE
,
result
);
result
,
unit
);
delete
result
;
}
else
...
...
@@ -2664,18 +2668,21 @@ static void
mysql_init_query
(
THD
*
thd
)
{
DBUG_ENTER
(
"mysql_init_query"
);
thd
->
lex
.
select_lex
.
item_list
.
empty
();
thd
->
lex
.
unit
.
init_query
();
thd
->
lex
.
unit
.
init_select
();
thd
->
lex
.
select_lex
.
init_query
();
thd
->
lex
.
unit
.
slave
=
&
thd
->
lex
.
select_lex
;
thd
->
lex
.
unit
.
select_limit
=
thd
->
default_select_limit
;
//Global limit
thd
->
lex
.
select_lex
.
master
=
&
thd
->
lex
.
unit
;
thd
->
lex
.
select_lex
.
prev
=
&
thd
->
lex
.
unit
.
slave
;
thd
->
lex
.
value_list
.
empty
();
thd
->
lex
.
select_lex
.
table_list
.
elements
=
0
;
thd
->
free_list
=
0
;
thd
->
lex
.
union_option
=
0
;
thd
->
lex
.
select
=
thd
->
lex
.
last_select
=
&
thd
->
lex
.
select_lex
;
thd
->
lex
.
select_lex
.
table_list
.
first
=
0
;
thd
->
lex
.
select_lex
.
table_list
.
next
=
(
byte
**
)
&
thd
->
lex
.
select_lex
.
table_list
.
first
;
thd
->
lex
.
select_lex
.
next
=
0
;
thd
->
fatal_error
=
0
;
// Safety
thd
->
last_insert_id_used
=
thd
->
query_start_used
=
thd
->
insert_id_used
=
0
;
thd
->
sent_row_count
=
thd
->
examined_row_count
=
0
;
thd
->
safe_to_cache_query
=
1
;
thd
->
free_list
=
0
;
thd
->
lex
.
union_option
=
0
;
thd
->
lex
.
select
=
&
thd
->
lex
.
select_lex
;
thd
->
fatal_error
=
0
;
// Safety
thd
->
last_insert_id_used
=
thd
->
query_start_used
=
thd
->
insert_id_used
=
0
;
thd
->
sent_row_count
=
thd
->
examined_row_count
=
0
;
thd
->
safe_to_cache_query
=
1
;
DBUG_VOID_RETURN
;
}
...
...
@@ -2683,53 +2690,53 @@ void
mysql_init_select
(
LEX
*
lex
)
{
SELECT_LEX
*
select_lex
=
lex
->
select
;
select_lex
->
where
=
select_lex
->
having
=
0
;
select_lex
->
init_select
()
;
select_lex
->
select_limit
=
lex
->
thd
->
default_select_limit
;
select_lex
->
offset_limit
=
0
;
select_lex
->
options
=
0
;
select_lex
->
linkage
=
UNSPECIFIED_TYPE
;
lex
->
exchange
=
0
;
lex
->
proc_list
.
first
=
0
;
select_lex
->
order_list
.
elements
=
select_lex
->
group_list
.
elements
=
0
;
select_lex
->
order_list
.
first
=
0
;
select_lex
->
order_list
.
next
=
(
byte
**
)
&
select_lex
->
order_list
.
first
;
select_lex
->
group_list
.
first
=
0
;
select_lex
->
group_list
.
next
=
(
byte
**
)
&
select_lex
->
group_list
.
first
;
select_lex
->
next
=
select_lex
->
prev
=
(
SELECT_LEX
*
)
NULL
;
}
bool
mysql_new_select
(
LEX
*
lex
)
mysql_new_select
(
LEX
*
lex
,
bool
move_down
)
{
SELECT_LEX
*
select_lex
=
(
SELECT_LEX
*
)
lex
->
thd
->
calloc
(
sizeof
(
SELECT_LEX
));
if
(
!
select_lex
)
return
1
;
lex
->
select
=
lex
->
last_select
;
lex
->
select
->
next
=
select_lex
;
lex
->
select
=
lex
->
last_select
=
select_lex
;
select_lex
->
table_list
.
next
=
(
byte
**
)
&
select_lex
->
table_list
.
first
;
select_lex
->
item_list
.
empty
();
select_lex
->
when_list
.
empty
();
select_lex
->
expr_list
.
empty
();
select_lex
->
interval_list
.
empty
();
select_lex
->
use_index
.
empty
();
select_lex
->
ftfunc_list
.
empty
();
select_lex
->
init_query
();
select_lex
->
init_select
();
if
(
move_down
)
{
/* first select_lex of subselect or derived table */
SELECT_LEX_UNIT
*
unit
=
(
SELECT_LEX_UNIT
*
)
lex
->
thd
->
calloc
(
sizeof
(
SELECT_LEX_UNIT
));
if
(
!
unit
)
return
1
;
unit
->
init_query
();
unit
->
init_select
();
unit
->
include_down
(
lex
->
select
);
select_lex
->
include_down
(
unit
);
}
else
select_lex
->
include_neighbour
(
lex
->
select
);
((
SELECT_LEX_UNIT
*
)
select_lex
->
master
)
->
global_parameters
=
select_lex
;
select_lex
->
include_global
(
&
lex
->
select
->
link_next
);
lex
->
select
=
select_lex
;
return
0
;
}
void
mysql_init_multi_delete
(
LEX
*
lex
)
{
lex
->
sql_command
=
SQLCOM_DELETE_MULTI
;
lex
->
sql_command
=
SQLCOM_DELETE_MULTI
;
mysql_init_select
(
lex
);
lex
->
select
->
select_limit
=
HA_POS_ERROR
;
lex
->
auxilliary_table_list
=
lex
->
select_lex
.
table_list
;
lex
->
select
->
table_list
.
elements
=
0
;
lex
->
select
->
table_list
.
first
=
0
;
lex
->
select
->
table_list
.
next
=
(
byte
**
)
&
(
lex
->
select
->
table_list
.
first
);
lex
->
select
->
select_limit
=
HA_POS_ERROR
;
lex
->
auxilliary_table_list
=
lex
->
select_lex
.
table_list
;
lex
->
select
->
init_query
();
}
void
mysql_parse
(
THD
*
thd
,
char
*
inBuf
,
uint
length
)
mysql_parse
(
THD
*
thd
,
char
*
inBuf
,
uint
length
)
{
DBUG_ENTER
(
"mysql_parse"
);
...
...
@@ -3159,7 +3166,7 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias,
ptr
->
real_name_length
=
table
->
table
.
length
;
ptr
->
lock_type
=
flags
;
ptr
->
updating
=
updating
;
ptr
->
derived
=
(
SELECT_LEX
*
)
table
->
sel
;
ptr
->
derived
=
(
SELECT_LEX_UNIT
*
)
table
->
sel
;
if
(
use_index
)
ptr
->
use_index
=
(
List
<
String
>
*
)
thd
->
memdup
((
gptr
)
use_index
,
sizeof
(
*
use_index
));
...
...
@@ -3204,8 +3211,8 @@ static bool create_total_list(THD *thd, LEX *lex, TABLE_LIST **result)
SELECT_LEX
*
sl
;
TABLE_LIST
**
new_table_list
=
result
,
*
aux
;
*
new_table_list
=
0
;
// end result list
for
(
sl
=
&
lex
->
select_lex
;
sl
;
sl
=
sl
->
next
)
*
new_table_list
=
0
;
// end result list
for
(
sl
=
&
lex
->
select_lex
;
sl
;
sl
=
(
SELECT_LEX
*
)
sl
->
next
)
{
if
(
sl
->
order_list
.
first
&&
sl
->
next
&&
!
sl
->
braces
)
{
...
...
sql/sql_select.cc
View file @
906903b9
This diff is collapsed.
Click to expand it.
sql/sql_select.h
View file @
906903b9
...
...
@@ -173,6 +173,8 @@ class JOIN {
select_result
*
result
;
TMP_TABLE_PARAM
tmp_table_param
;
MYSQL_LOCK
*
lock
;
// unit structure (with global parameters) for this select
SELECT_LEX_UNIT
*
unit
;
};
...
...
@@ -187,7 +189,8 @@ void TEST_join(JOIN *join);
bool
store_val_in_field
(
Field
*
field
,
Item
*
val
);
TABLE
*
create_tmp_table
(
THD
*
thd
,
TMP_TABLE_PARAM
*
param
,
List
<
Item
>
&
fields
,
ORDER
*
group
,
bool
distinct
,
bool
save_sum_fields
,
bool
allow_distinct_limit
,
ulong
select_options
);
bool
allow_distinct_limit
,
ulong
select_options
,
SELECT_LEX_UNIT
*
unit
);
void
free_tmp_table
(
THD
*
thd
,
TABLE
*
entry
);
void
count_field_types
(
TMP_TABLE_PARAM
*
param
,
List
<
Item
>
&
fields
,
bool
reset_with_sum_func
);
...
...
sql/sql_union.cc
View file @
906903b9
...
...
@@ -27,8 +27,8 @@
int
mysql_union
(
THD
*
thd
,
LEX
*
lex
,
select_result
*
result
)
{
SELECT_LEX
*
sl
,
*
last_sl
,
*
lex_sl
;
ORDER
*
order
;
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
;
...
...
@@ -39,12 +39,12 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
TMP_TABLE_PARAM
tmp_table_param
;
select_union
*
union_result
;
DBUG_ENTER
(
"mysql_union"
);
st_select_lex_node
*
global
;
/* Fix tables 'to-be-unioned-from' list to point at opened tables */
last_sl
=
&
lex
->
select_lex
;
for
(
sl
=
last_sl
;
sl
&&
sl
->
linkage
!=
NOT_A_SELECT
;
last_sl
=
sl
,
sl
=
sl
->
next
)
for
(
sl
=
&
lex
->
select_lex
;
sl
;
sl
=
(
SELECT_LEX
*
)
sl
->
next
)
{
for
(
TABLE_LIST
*
cursor
=
(
TABLE_LIST
*
)
sl
->
table_list
.
first
;
cursor
;
...
...
@@ -52,31 +52,13 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
cursor
->
table
=
((
TABLE_LIST
*
)
cursor
->
table
)
->
table
;
}
/*
last_sel now points at the last select where the ORDER BY is stored
*/
if
(
sl
)
/*
Global option
*/
if
(
((
void
*
)(
global
=
unit
->
global_parameters
))
==
((
void
*
)
unit
)
)
{
/*
The found SL is an extra SELECT_LEX argument that contains
the ORDER BY and LIMIT parameter for the whole UNION
*/
lex_sl
=
sl
;
order
=
(
ORDER
*
)
lex_sl
->
order_list
.
first
;
found_rows_for_union
=
lex
->
select_lex
.
options
&
OPTION_FOUND_ROWS
&&
!
describe
&&
sl
->
select_limit
;
found_rows_for_union
=
lex
->
select_lex
.
options
&
OPTION_FOUND_ROWS
&&
!
describe
&&
global
->
select_limit
;
if
(
found_rows_for_union
)
lex
->
select_lex
.
options
^=
OPTION_FOUND_ROWS
;
// This is done to eliminate unnecessary slowing down of the first query
if
(
!
order
||
!
describe
)
last_sl
->
next
=
0
;
// Remove this extra element
}
else
if
(
!
last_sl
->
braces
)
{
lex_sl
=
last_sl
;
// ORDER BY is here
order
=
(
ORDER
*
)
lex_sl
->
order_list
.
first
;
}
else
{
lex_sl
=
0
;
order
=
0
;
}
if
(
describe
)
...
...
@@ -113,11 +95,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
,
1
,
0
,
(
lex
->
select_lex
.
options
|
thd
->
options
|
TMP_TABLE_ALL_COLUMNS
))))
if
(
!
(
table
=
create_tmp_table
(
thd
,
&
tmp_table_param
,
item_list
,
(
ORDER
*
)
0
,
!
describe
&
!
lex
->
union_option
,
1
,
0
,
(
lex
->
select_lex
.
options
|
thd
->
options
|
TMP_TABLE_ALL_COLUMNS
),
unit
)))
DBUG_RETURN
(
-
1
);
table
->
file
->
extra
(
HA_EXTRA_WRITE_CACHE
);
table
->
file
->
extra
(
HA_EXTRA_IGNORE_DUP_KEY
);
...
...
@@ -133,25 +116,29 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
}
union_result
->
save_time_stamp
=!
describe
;
for
(
sl
=
&
lex
->
select_lex
;
sl
;
sl
=
sl
->
next
)
for
(
sl
=
&
lex
->
select_lex
;
sl
;
sl
=
(
SELECT_LEX
*
)
sl
->
next
)
{
lex
->
select
=
sl
;
thd
->
offset_limit
=
sl
->
offset_limit
;
thd
->
select_limit
=
sl
->
select_limit
+
sl
->
offset_limit
;
if
(
thd
->
select_limi
t
<
sl
->
select_limit
)
thd
->
select_limi
t
=
HA_POS_ERROR
;
// no limit
if
(
thd
->
select_limi
t
==
HA_POS_ERROR
)
unit
->
offset_limit_cnt
=
sl
->
offset_limit
;
unit
->
select_limit_cnt
=
sl
->
select_limit
+
sl
->
offset_limit
;
if
(
unit
->
select_limit_cn
t
<
sl
->
select_limit
)
unit
->
select_limit_cn
t
=
HA_POS_ERROR
;
// no limit
if
(
unit
->
select_limit_cn
t
==
HA_POS_ERROR
)
sl
->
options
&=
~
OPTION_FOUND_ROWS
;
res
=
mysql_select
(
thd
,
(
describe
&&
sl
->
linkage
==
NOT_A_SELECT
)
?
first_table
:
(
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
);
res
=
mysql_select
(
thd
,
(
describe
&&
sl
->
linkage
==
GLOBAL_OPTIONS_TYPE
)
?
first_table
:
(
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
;
}
...
...
@@ -183,26 +170,20 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
}
if
(
!
thd
->
fatal_error
)
// Check if EOM
{
if
(
lex_sl
)
{
thd
->
offset_limit
=
lex_sl
->
offset_limit
;
thd
->
select_limit
=
lex_sl
->
select_limit
+
lex_sl
->
offset_limit
;
if
(
thd
->
select_limit
<
lex_sl
->
select_limit
)
thd
->
select_limit
=
HA_POS_ERROR
;
// no limit
if
(
thd
->
select_limit
==
HA_POS_ERROR
)
thd
->
options
&=
~
OPTION_FOUND_ROWS
;
}
else
{
thd
->
offset_limit
=
0
;
thd
->
select_limit
=
thd
->
default_select_limit
;
}
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
)
thd
->
options
&=
~
OPTION_FOUND_ROWS
;
if
(
describe
)
thd
->
select_limit
=
HA_POS_ERROR
;
// no limit
res
=
mysql_select
(
thd
,
&
result_table_list
,
item_list
,
NULL
,
(
describe
)
?
0
:
order
,
(
ORDER
*
)
NULL
,
NULL
,
(
ORDER
*
)
NULL
,
thd
->
options
,
result
);
unit
->
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
,
(
ORDER
*
)
NULL
,
NULL
,
(
ORDER
*
)
NULL
,
thd
->
options
,
result
,
unit
);
if
(
found_rows_for_union
&&
!
res
)
thd
->
limit_found_rows
=
(
ulonglong
)
table
->
file
->
records
;
}
...
...
@@ -226,7 +207,7 @@ select_union::select_union(TABLE *table_par)
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
;
info
.
handle_duplicates
=
DUP_IGNORE
;
}
select_union
::~
select_union
()
...
...
@@ -234,8 +215,9 @@ select_union::~select_union()
}
int
select_union
::
prepare
(
List
<
Item
>
&
list
)
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
,
...
...
@@ -247,9 +229,9 @@ int select_union::prepare(List<Item> &list)
bool
select_union
::
send_data
(
List
<
Item
>
&
values
)
{
if
(
thd
->
offset_limi
t
)
if
(
unit
->
offset_limit_cn
t
)
{
// using limit offset,count
thd
->
offset_limi
t
--
;
unit
->
offset_limit_cn
t
--
;
return
0
;
}
fill_record
(
table
->
field
,
values
);
...
...
sql/sql_update.cc
View file @
906903b9
...
...
@@ -379,9 +379,10 @@ multi_update::multi_update(THD *thd_arg, TABLE_LIST *ut, List<Item> &fs,
}
int
multi_update
::
prepare
(
List
<
Item
>
&
values
)
multi_update
::
prepare
(
List
<
Item
>
&
values
,
SELECT_LEX_UNIT
*
u
)
{
DBUG_ENTER
(
"multi_update::prepare"
);
unit
=
u
;
do_update
=
true
;
thd
->
count_cuted_fields
=
1
;
thd
->
cuted_fields
=
0L
;
...
...
@@ -466,15 +467,19 @@ multi_update::prepare(List<Item> &values)
}
if
(
counter
)
{
Field_string
offset
(
table_ref
->
table
->
file
->
ref_length
,
false
,
"offset"
,
table_ref
->
table
,
true
);
Field_string
offset
(
table_ref
->
table
->
file
->
ref_length
,
false
,
"offset"
,
table_ref
->
table
,
true
);
temp_fields
->
push_front
(
new
Item_field
(((
Field
*
)
&
offset
)));
// Here I make tmp tables
int
cnt
=
counter
-
1
;
TMP_TABLE_PARAM
tmp_table_param
;
bzero
((
char
*
)
&
tmp_table_param
,
sizeof
(
tmp_table_param
));
tmp_table_param
.
field_count
=
temp_fields
->
elements
;
if
(
!
(
tmp_tables
[
cnt
]
=
create_tmp_table
(
thd
,
&
tmp_table_param
,
*
temp_fields
,
(
ORDER
*
)
0
,
1
,
0
,
0
,
TMP_TABLE_ALL_COLUMNS
)))
if
(
!
(
tmp_tables
[
cnt
]
=
create_tmp_table
(
thd
,
&
tmp_table_param
,
*
temp_fields
,
(
ORDER
*
)
0
,
1
,
0
,
0
,
TMP_TABLE_ALL_COLUMNS
,
unit
)))
{
error
=
1
;
// A proper error message is due here
DBUG_RETURN
(
1
);
...
...
sql/sql_yacc.yy
View file @
906903b9
...
...
@@ -1449,7 +1449,14 @@ select:
select_init:
SELECT_SYM select_part2 { Select->braces=false; } union
|
'(' SELECT_SYM select_part2 ')' { Select->braces=true;} union_opt
'(' SELECT_SYM select_part2 ')'
{
SELECT_LEX * sel=Select;
sel->braces=true;
/* select in braces, can't contain global parameters */
((SELECT_LEX_UNIT*)sel->master)->global_parameters=
sel->master;
} union_opt
select_part2:
...
...
@@ -2155,23 +2162,22 @@ join_table:
| '(' SELECT_SYM select_part3 ')' opt_table_alias
{
LEX *lex=Lex;
SELECT_LEX
*select_to_execute= lex->select
;
lex->select=
lex->select->prev
;
if (!($$=
add_table_to_list(new Table_ident(select_to_execute
),
$5,0,TL_UNLOCK)))
SELECT_LEX
_UNIT *unit= (SELECT_LEX_UNIT*) lex->select->master
;
lex->select=
(SELECT_LEX*) unit->master
;
if (!($$=
add_table_to_list(new Table_ident(unit
),
$5,0,TL_UNLOCK)))
YYABORT;
}
select_part3:
{
LEX *lex=Lex;
lex->derived_tables=true;
SELECT_LEX *tmp=lex->select;
if (lex->select->linkage == NOT_A_SELECT || mysql_new_select(lex
))
LEX *lex=
Lex;
lex->derived_tables=
true;
if (lex->select->linkage == GLOBAL_OPTIONS_TYPE ||
mysql_new_select(lex, 1
))
YYABORT;
mysql_init_select(lex);
lex->select->linkage=DERIVED_TABLE_TYPE;
lex->select->prev=tmp;
lex->select->linkage= DERIVED_TABLE_TYPE;
}
select_options select_item_list select_intoto
...
...
@@ -3811,7 +3817,8 @@ union_list:
net_printf(&lex->thd->net, ER_WRONG_USAGE,"UNION","INTO");
YYABORT;
}
if (lex->select->linkage == NOT_A_SELECT || mysql_new_select(lex))
if (lex->select->linkage == GLOBAL_OPTIONS_TYPE ||
mysql_new_select(lex, 0))
YYABORT;
lex->select->linkage=UNION_TYPE;
}
...
...
@@ -3826,10 +3833,15 @@ optional_order_or_limit:
|
{
LEX *lex=Lex;
if (!lex->select->braces
|| mysql_new_select(lex)
)
if (!lex->select->braces)
YYABORT;
mysql_init_select(lex);
lex->select->linkage=NOT_A_SELECT;
((SELECT_LEX_UNIT*)lex->select->master)->global_parameters=
lex->select->master;
/*
Following type conversion looks like hack, but all that need SELECT_LEX
fields always check linkage type.
*/
lex->select= (SELECT_LEX*)lex->select->master;
lex->select->select_limit=lex->thd->default_select_limit;
}
opt_order_clause limit_clause
...
...
sql/table.h
View file @
906903b9
...
...
@@ -139,18 +139,18 @@ typedef struct st_table_list {
struct
st_table_list
*
next
;
char
*
db
,
*
name
,
*
real_name
;
uint32
db_length
,
real_name_length
;
Item
*
on_expr
;
/* Used with outer join */
struct
st_table_list
*
natural_join
;
/* natural join on this table*/
Item
*
on_expr
;
/* Used with outer join */
struct
st_table_list
*
natural_join
;
/* natural join on this table*/
/* ... join ... USE INDEX ... IGNORE INDEX */
List
<
String
>
*
use_index
,
*
ignore_index
;
List
<
String
>
*
use_index
,
*
ignore_index
;
TABLE
*
table
;
GRANT_INFO
grant
;
thr_lock_type
lock_type
;
uint
outer_join
;
/* Which join type */
bool
straight
;
/* optimize with prev table */
bool
updating
;
/* for replicate-do/ignore table */
bool
shared
;
/* Used twice in union */
void
*
derived
;
uint
outer_join
;
/* Which join type */
bool
straight
;
/* optimize with prev table */
bool
updating
;
/* for replicate-do/ignore table */
bool
shared
;
/* Used twice in union */
void
*
derived
;
/* SELECT_LEX_UNIT of derived table */
}
TABLE_LIST
;
typedef
struct
st_changed_table_list
{
...
...
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