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
fd98ed36
Commit
fd98ed36
authored
Feb 19, 2004
by
unknown
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Manual merge
parent
f4353d48
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
224 additions
and
138 deletions
+224
-138
sql/item.h
sql/item.h
+60
-29
sql/opt_range.cc
sql/opt_range.cc
+73
-31
sql/sql_select.cc
sql/sql_select.cc
+91
-78
No files found.
sql/item.h
View file @
fd98ed36
...
...
@@ -126,8 +126,8 @@ class Item {
top AND/OR ctructure of WHERE clause to protect it of
optimisation changes in prepared statements
*/
Item
(
THD
*
thd
,
Item
&
item
);
virtual
~
Item
()
{
name
=
0
;
cleanup
();
}
/*lint -e1509 */
Item
(
THD
*
thd
,
Item
*
item
);
virtual
~
Item
()
{
name
=
0
;
}
/*lint -e1509 */
void
set_name
(
const
char
*
str
,
uint
length
,
CHARSET_INFO
*
cs
);
void
init_make_field
(
Send_field
*
tmp_field
,
enum
enum_field_types
type
);
virtual
void
cleanup
()
{
fixed
=
0
;
}
...
...
@@ -206,6 +206,7 @@ class Item {
virtual
Item
*
get_tmp_table_item
(
THD
*
thd
)
{
return
copy_or_same
(
thd
);
}
CHARSET_INFO
*
default_charset
()
const
;
virtual
CHARSET_INFO
*
compare_collation
()
{
return
NULL
;
}
virtual
bool
walk
(
Item_processor
processor
,
byte
*
arg
)
{
...
...
@@ -239,6 +240,11 @@ class Item {
/* Used in sql_select.cc:eliminate_not_funcs() */
virtual
Item
*
neg_transformer
()
{
return
NULL
;
}
void
delete_self
()
{
cleanup
();
delete
this
;
}
};
...
...
@@ -304,7 +310,10 @@ class Item_splocal : public Item
inline
void
make_field
(
Send_field
*
field
)
{
this_item
()
->
make_field
(
field
);
Item
*
it
=
this_item
();
it
->
set_name
(
m_name
.
str
,
m_name
.
length
,
system_charset_info
);
it
->
make_field
(
field
);
}
inline
Item_result
result_type
()
const
...
...
@@ -326,6 +335,11 @@ class Item_splocal : public Item
{
str
->
append
(
m_name
.
str
,
m_name
.
length
);
}
inline
bool
send
(
Protocol
*
protocol
,
String
*
str
)
{
return
this_item
()
->
send
(
protocol
,
str
);
}
};
...
...
@@ -339,7 +353,7 @@ class Item_ident :public Item
st_select_lex
*
depended_from
;
Item_ident
(
const
char
*
db_name_par
,
const
char
*
table_name_par
,
const
char
*
field_name_par
);
Item_ident
(
THD
*
thd
,
Item_ident
&
item
);
Item_ident
(
THD
*
thd
,
Item_ident
*
item
);
const
char
*
full_name
()
const
;
bool
remove_dependence_processor
(
byte
*
arg
);
...
...
@@ -362,7 +376,7 @@ class Item_field :public Item_ident
item_equal
(
0
)
{
collation
.
set
(
DERIVATION_IMPLICIT
);
}
// Constructor need to process subselect with temporary tables (see Item)
Item_field
(
THD
*
thd
,
Item_field
&
item
);
Item_field
(
THD
*
thd
,
Item_field
*
item
);
Item_field
(
Field
*
field
);
enum
Type
type
()
const
{
return
FIELD_ITEM
;
}
bool
eq
(
const
Item
*
item
,
bool
binary_cmp
)
const
;
...
...
@@ -393,6 +407,7 @@ class Item_field :public Item_ident
bool
get_time
(
TIME
*
ltime
);
bool
is_null
()
{
return
field
->
is_null
();
}
Item
*
get_tmp_table_item
(
THD
*
thd
);
void
cleanup
();
Item_equal
*
find_item_equal
(
COND_EQUAL
*
cond_equal
);
Item
*
equal_fields_propagator
(
byte
*
arg
);
bool
replace_equal_field_processor
(
byte
*
arg
);
...
...
@@ -583,7 +598,7 @@ class Item_string :public Item
CHARSET_INFO
*
cs
,
Derivation
dv
=
DERIVATION_COERCIBLE
)
{
collation
.
set
(
cs
,
dv
);
str_value
.
set
(
str
,
length
,
cs
);
str_value
.
set
_or_copy_aligned
(
str
,
length
,
cs
);
/*
We have to have a different max_length than 'length' here to
ensure that we get the right length if we do use the item
...
...
@@ -599,12 +614,11 @@ class Item_string :public Item
CHARSET_INFO
*
cs
,
Derivation
dv
=
DERIVATION_COERCIBLE
)
{
collation
.
set
(
cs
,
dv
);
str_value
.
set
(
str
,
length
,
cs
);
str_value
.
set
_or_copy_aligned
(
str
,
length
,
cs
);
max_length
=
str_value
.
numchars
()
*
cs
->
mbmaxlen
;
set_name
(
name_par
,
0
,
cs
);
decimals
=
NOT_FIXED_DEC
;
}
~
Item_string
()
{}
enum
Type
type
()
const
{
return
STRING_ITEM
;
}
double
val
()
{
...
...
@@ -671,7 +685,6 @@ class Item_varbinary :public Item
{
public:
Item_varbinary
(
const
char
*
str
,
uint
str_length
);
~
Item_varbinary
()
{}
enum
Type
type
()
const
{
return
VARBIN_ITEM
;
}
double
val
()
{
return
(
double
)
Item_varbinary
::
val_int
();
}
longlong
val_int
();
...
...
@@ -688,8 +701,8 @@ class Item_result_field :public Item /* Item with result field */
Field
*
result_field
;
/* Save result here */
Item_result_field
()
:
result_field
(
0
)
{}
// Constructor used for Item_sum/Item_cond_and/or (see Item comment)
Item_result_field
(
THD
*
thd
,
Item_result_field
&
item
)
:
Item
(
thd
,
item
),
result_field
(
item
.
result_field
)
Item_result_field
(
THD
*
thd
,
Item_result_field
*
item
)
:
Item
(
thd
,
item
),
result_field
(
item
->
result_field
)
{}
~
Item_result_field
()
{}
/* Required with gcc 2.95 */
Field
*
get_tmp_table_field
()
{
return
result_field
;
}
...
...
@@ -708,20 +721,25 @@ class Item_result_field :public Item /* Item with result field */
class
Item_ref
:
public
Item_ident
{
public:
Field
*
result_field
;
/* Save result here */
Field
*
result_field
;
/* Save result here */
Item
**
ref
;
Item_ref
(
const
char
*
db_par
,
const
char
*
table_name_par
,
const
char
*
field_name_par
)
:
Item_ident
(
db_par
,
table_name_par
,
field_name_par
),
ref
(
0
)
{}
Item_ref
(
Item
**
item
,
const
char
*
table_name_par
,
const
char
*
field_name_par
)
:
Item_ident
(
NullS
,
table_name_par
,
field_name_par
),
ref
(
item
)
{}
Item
**
hook_ptr
;
/* These two to restore */
Item
*
orig_item
;
/* things in 'cleanup()' */
Item_ref
(
Item
**
hook
,
Item
*
original
,
const
char
*
db_par
,
const
char
*
table_name_par
,
const
char
*
field_name_par
)
:
Item_ident
(
db_par
,
table_name_par
,
field_name_par
),
ref
(
0
),
hook_ptr
(
hook
),
orig_item
(
original
)
{}
Item_ref
(
Item
**
item
,
Item
**
hook
,
const
char
*
table_name_par
,
const
char
*
field_name_par
)
:
Item_ident
(
NullS
,
table_name_par
,
field_name_par
),
ref
(
item
),
hook_ptr
(
hook
),
orig_item
(
hook
?
*
hook
:
0
)
{}
// Constructor need to process subselect with temporary tables (see Item)
Item_ref
(
THD
*
thd
,
Item_ref
&
item
)
:
Item_ident
(
thd
,
item
),
ref
(
item
.
ref
)
{}
Item_ref
(
THD
*
thd
,
Item_ref
*
item
,
Item
**
hook
)
:
Item_ident
(
thd
,
item
),
ref
(
item
->
ref
),
hook_ptr
(
hook
),
orig_item
(
hook
?
*
hook
:
0
)
{}
enum
Type
type
()
const
{
return
REF_ITEM
;
}
bool
eq
(
const
Item
*
item
,
bool
binary_cmp
)
const
{
return
ref
&&
(
*
ref
)
->
eq
(
item
,
binary_cmp
);
}
~
Item_ref
()
{
if
(
ref
&&
(
*
ref
)
&&
(
*
ref
)
!=
this
)
delete
*
ref
;
}
double
val
()
{
double
tmp
=
(
*
ref
)
->
val_result
();
...
...
@@ -766,6 +784,7 @@ class Item_ref :public Item_ident
}
Item
*
real_item
()
{
return
*
ref
;
}
void
print
(
String
*
str
);
void
cleanup
();
};
class
Item_in_subselect
;
...
...
@@ -776,7 +795,7 @@ class Item_ref_null_helper: public Item_ref
public:
Item_ref_null_helper
(
Item_in_subselect
*
master
,
Item
**
item
,
const
char
*
table_name_par
,
const
char
*
field_name_par
)
:
Item_ref
(
item
,
table_name_par
,
field_name_par
),
owner
(
master
)
{}
Item_ref
(
item
,
NULL
,
table_name_par
,
field_name_par
),
owner
(
master
)
{}
double
val
();
longlong
val_int
();
String
*
val_str
(
String
*
s
);
...
...
@@ -840,7 +859,6 @@ class Item_copy_string :public Item
name
=
item
->
name
;
cached_field_type
=
item
->
field_type
();
}
~
Item_copy_string
()
{
delete
item
;
}
enum
Type
type
()
const
{
return
COPY_STR_ITEM
;
}
enum
Item_result
result_type
()
const
{
return
STRING_RESULT
;
}
enum_field_types
field_type
()
const
{
return
cached_field_type
;
}
...
...
@@ -997,13 +1015,15 @@ class Item_cache: public Item
void
set_used_tables
(
table_map
map
)
{
used_table_map
=
map
;
}
virtual
bool
allocate
(
uint
i
)
{
return
0
;
};
virtual
bool
setup
(
Item
*
item
)
{
example
=
item
;
return
0
;
};
virtual
void
store
(
Item
*
)
=
0
;
void
set_len_n_dec
(
uint32
max_len
,
uint8
dec
)
virtual
bool
setup
(
Item
*
item
)
{
max_length
=
max_len
;
decimals
=
dec
;
}
example
=
item
;
max_length
=
item
->
max_length
;
decimals
=
item
->
decimals
;
collation
.
set
(
item
->
collation
);
return
0
;
};
virtual
void
store
(
Item
*
)
=
0
;
enum
Type
type
()
const
{
return
CACHE_ITEM
;
}
static
Item_cache
*
get_cache
(
Item_result
type
);
table_map
used_tables
()
const
{
return
used_table_map
;
}
...
...
@@ -1028,7 +1048,7 @@ class Item_cache_real: public Item_cache
double
value
;
public:
Item_cache_real
()
:
Item_cache
()
{}
void
store
(
Item
*
item
);
double
val
()
{
return
value
;
}
longlong
val_int
()
{
return
(
longlong
)
(
value
+
(
value
>
0
?
0.5
:
-
0.5
));
}
...
...
@@ -1101,6 +1121,11 @@ class Item_cache_row: public Item_cache
bool
check_cols
(
uint
c
);
bool
null_inside
();
void
bring_value
();
void
cleanup
()
{
Item_cache
::
cleanup
();
values
=
0
;
}
};
...
...
@@ -1111,6 +1136,7 @@ class Item_type_holder: public Item
{
protected:
Item_result
item_type
;
Item_result
orig_type
;
Field
*
field_example
;
public:
Item_type_holder
(
THD
*
,
Item
*
);
...
...
@@ -1122,6 +1148,11 @@ class Item_type_holder: public Item
String
*
val_str
(
String
*
);
bool
join_types
(
THD
*
thd
,
Item
*
);
Field
*
example
()
{
return
field_example
;
}
void
cleanup
()
{
Item
::
cleanup
();
item_type
=
orig_type
;
}
};
...
...
sql/opt_range.cc
View file @
fd98ed36
...
...
@@ -301,10 +301,11 @@ typedef struct st_qsel_param {
uint
imerge_cost_buff_size
;
/* size of the buffer */
}
PARAM
;
static
SEL_TREE
*
get_mm_parts
(
PARAM
*
param
,
Field
*
field
,
static
SEL_TREE
*
get_mm_parts
(
PARAM
*
param
,
COND
*
cond_func
,
Field
*
field
,
Item_func
::
Functype
type
,
Item
*
value
,
Item_result
cmp_type
);
static
SEL_ARG
*
get_mm_leaf
(
PARAM
*
param
,
Field
*
field
,
KEY_PART
*
key_part
,
static
SEL_ARG
*
get_mm_leaf
(
PARAM
*
param
,
COND
*
cond_func
,
Field
*
field
,
KEY_PART
*
key_part
,
Item_func
::
Functype
type
,
Item
*
value
);
static
SEL_TREE
*
get_mm_tree
(
PARAM
*
param
,
COND
*
cond
);
static
ha_rows
check_quick_select
(
PARAM
*
param
,
uint
index
,
SEL_ARG
*
key_tree
);
...
...
@@ -612,14 +613,25 @@ SQL_SELECT::SQL_SELECT() :quick(0),cond(0),free_cond(0)
}
SQL_SELECT
::~
SQL_SELECT
()
void
SQL_SELECT
::
cleanup
()
{
delete
quick
;
quick
=
0
;
if
(
free_cond
)
{
free_cond
=
0
;
delete
cond
;
cond
=
0
;
}
close_cached_file
(
&
file
);
}
SQL_SELECT
::~
SQL_SELECT
()
{
cleanup
();
}
#undef index // Fix for Unixware 7
QUICK_SELECT_I
::
QUICK_SELECT_I
()
...
...
@@ -1746,7 +1758,8 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
static
SEL_TREE
*
get_mm_parts
(
PARAM
*
param
,
Field
*
field
,
Item_func
::
Functype
type
,
get_mm_parts
(
PARAM
*
param
,
COND
*
cond_func
,
Field
*
field
,
Item_func
::
Functype
type
,
Item
*
value
,
Item_result
cmp_type
)
{
DBUG_ENTER
(
"get_mm_parts"
);
...
...
@@ -1768,7 +1781,8 @@ get_mm_parts(PARAM *param, Field *field, Item_func::Functype type,
DBUG_RETURN
(
0
);
// OOM
if
(
!
value
||
!
(
value
->
used_tables
()
&
~
param
->
read_tables
))
{
sel_arg
=
get_mm_leaf
(
param
,
key_part
->
field
,
key_part
,
type
,
value
);
sel_arg
=
get_mm_leaf
(
param
,
cond_func
,
key_part
->
field
,
key_part
,
type
,
value
);
if
(
!
sel_arg
)
continue
;
if
(
sel_arg
->
type
==
SEL_ARG
::
IMPOSSIBLE
)
...
...
@@ -1794,7 +1808,7 @@ get_mm_parts(PARAM *param, Field *field, Item_func::Functype type,
static
SEL_ARG
*
get_mm_leaf
(
PARAM
*
param
,
Field
*
field
,
KEY_PART
*
key_part
,
get_mm_leaf
(
PARAM
*
param
,
COND
*
conf_func
,
Field
*
field
,
KEY_PART
*
key_part
,
Item_func
::
Functype
type
,
Item
*
value
)
{
uint
maybe_null
=
(
uint
)
field
->
real_maybe_null
(),
copies
;
...
...
@@ -1803,6 +1817,32 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part,
char
*
str
,
*
str2
;
DBUG_ENTER
(
"get_mm_leaf"
);
if
(
!
value
)
// IS NULL or IS NOT NULL
{
if
(
field
->
table
->
outer_join
)
// Can't use a key on this
DBUG_RETURN
(
0
);
if
(
!
maybe_null
)
// Not null field
DBUG_RETURN
(
type
==
Item_func
::
ISNULL_FUNC
?
&
null_element
:
0
);
if
(
!
(
tree
=
new
SEL_ARG
(
field
,
is_null_string
,
is_null_string
)))
DBUG_RETURN
(
0
);
// out of memory
if
(
type
==
Item_func
::
ISNOTNULL_FUNC
)
{
tree
->
min_flag
=
NEAR_MIN
;
/* IS NOT NULL -> X > NULL */
tree
->
max_flag
=
NO_MAX_RANGE
;
}
DBUG_RETURN
(
tree
);
}
/*
We can't use an index when comparing strings of
different collations
*/
if
(
field
->
result_type
()
==
STRING_RESULT
&&
value
->
result_type
()
==
STRING_RESULT
&&
key_part
->
image_type
==
Field
::
itRAW
&&
((
Field_str
*
)
field
)
->
charset
()
!=
conf_func
->
compare_collation
())
DBUG_RETURN
(
0
);
if
(
type
==
Item_func
::
LIKE_FUNC
)
{
bool
like_error
;
...
...
@@ -1866,22 +1906,6 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part,
DBUG_RETURN
(
new
SEL_ARG
(
field
,
min_str
,
max_str
));
}
if
(
!
value
)
// IS NULL or IS NOT NULL
{
if
(
field
->
table
->
outer_join
)
// Can't use a key on this
DBUG_RETURN
(
0
);
if
(
!
maybe_null
)
// Not null field
DBUG_RETURN
(
type
==
Item_func
::
ISNULL_FUNC
?
&
null_element
:
0
);
if
(
!
(
tree
=
new
SEL_ARG
(
field
,
is_null_string
,
is_null_string
)))
DBUG_RETURN
(
0
);
// out of memory
if
(
type
==
Item_func
::
ISNOTNULL_FUNC
)
{
tree
->
min_flag
=
NEAR_MIN
;
/* IS NOT NULL -> X > NULL */
tree
->
max_flag
=
NO_MAX_RANGE
;
}
DBUG_RETURN
(
tree
);
}
if
(
!
field
->
optimize_range
(
param
->
real_keynr
[
key_part
->
key
])
&&
type
!=
Item_func
::
EQ_FUNC
&&
type
!=
Item_func
::
EQUAL_FUNC
)
...
...
@@ -1895,7 +1919,7 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part,
value
->
result_type
()
!=
STRING_RESULT
&&
field
->
cmp_type
()
!=
value
->
result_type
())
DBUG_RETURN
(
0
);
if
(
value
->
save_in_field
(
field
,
1
)
>
0
)
{
/* This happens when we try to insert a NULL field in a not null column */
...
...
@@ -3097,6 +3121,7 @@ check_quick_select(PARAM *param,uint idx,SEL_ARG *tree)
param
->
table
->
quick_rows
[
key
]
=
records
;
param
->
table
->
quick_key_parts
[
key
]
=
param
->
max_key_part
+
1
;
}
DBUG_PRINT
(
"exit"
,
(
"Records: %lu"
,
(
ulong
)
records
));
DBUG_RETURN
(
records
);
}
...
...
@@ -3440,8 +3465,30 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
key_part
->
part_length
+=
HA_KEY_BLOB_LENGTH
;
key_part
->
null_bit
=
key_info
->
key_part
[
part
].
null_bit
;
}
if
(
!
insert_dynamic
(
&
quick
->
ranges
,(
gptr
)
&
range
))
return
quick
;
if
(
insert_dynamic
(
&
quick
->
ranges
,(
gptr
)
&
range
))
goto
err
;
/*
Add a NULL range if REF_OR_NULL optimization is used.
For example:
if we have "WHERE A=2 OR A IS NULL" we created the (A=2) range above
and have ref->null_ref_key set. Will create a new NULL range here.
*/
if
(
ref
->
null_ref_key
)
{
QUICK_RANGE
*
null_range
;
*
ref
->
null_ref_key
=
1
;
// Set null byte then create a range
if
(
!
(
null_range
=
new
QUICK_RANGE
(
ref
->
key_buff
,
ref
->
key_length
,
ref
->
key_buff
,
ref
->
key_length
,
EQ_RANGE
)))
goto
err
;
*
ref
->
null_ref_key
=
0
;
// Clear null byte
if
(
insert_dynamic
(
&
quick
->
ranges
,(
gptr
)
&
null_range
))
goto
err
;
}
return
quick
;
err:
delete
quick
;
...
...
@@ -3584,12 +3631,7 @@ int QUICK_RANGE_SELECT::get_next()
int
result
;
if
(
range
)
{
// Already read through key
/* result=((range->flag & EQ_RANGE) ?
file->index_next_same(record, (byte*) range->min_key,
range->min_length) :
file->index_next(record));
*/
result
=
((
range
->
flag
&
(
EQ_RANGE
|
GEOM_FLAG
)
)
?
result
=
((
range
->
flag
&
(
EQ_RANGE
|
GEOM_FLAG
))
?
file
->
index_next_same
(
record
,
(
byte
*
)
range
->
min_key
,
range
->
min_length
)
:
file
->
index_next
(
record
));
...
...
sql/sql_select.cc
View file @
fd98ed36
...
...
@@ -24,8 +24,6 @@
#include "mysql_priv.h"
#include "sql_select.h"
#include "opt_ft.h"
#include <m_ctype.h>
#include <hash.h>
#include <ft_global.h>
...
...
@@ -89,7 +87,7 @@ static int do_select(JOIN *join,List<Item> *fields,TABLE *tmp_table,
Procedure
*
proc
);
static
int
sub_select_cache
(
JOIN
*
join
,
JOIN_TAB
*
join_tab
,
bool
end_of_records
);
static
int
sub_select
(
JOIN
*
join
,
JOIN_TAB
*
join_tab
,
bool
end_of_records
);
static
int
flush_cached_records
(
JOIN
*
join
,
JOIN_TAB
*
join_tab
,
bool
skip
p
_last
);
static
int
flush_cached_records
(
JOIN
*
join
,
JOIN_TAB
*
join_tab
,
bool
skip_last
);
static
int
end_send
(
JOIN
*
join
,
JOIN_TAB
*
join_tab
,
bool
end_of_records
);
static
int
end_send_group
(
JOIN
*
join
,
JOIN_TAB
*
join_tab
,
bool
end_of_records
);
static
int
end_write
(
JOIN
*
join
,
JOIN_TAB
*
join_tab
,
bool
end_of_records
);
...
...
@@ -182,7 +180,6 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
register
SELECT_LEX
*
select_lex
=
&
lex
->
select_lex
;
DBUG_ENTER
(
"handle_select"
);
fix_tables_pointers
(
lex
->
all_selects_list
);
if
(
select_lex
->
next_select
())
res
=
mysql_union
(
thd
,
lex
,
result
,
&
lex
->
unit
);
else
...
...
@@ -309,7 +306,7 @@ JOIN::prepare(Item ***rref_pointer_array,
/* Check that all tables, fields, conds and order are ok */
if
(
setup_tables
(
tables_list
)
||
if
(
setup_tables
(
tables_list
,
0
)
||
setup_wild
(
thd
,
tables_list
,
fields_list
,
&
all_fields
,
wild_num
)
||
select_lex
->
setup_ref_array
(
thd
,
og_num
)
||
setup_fields
(
thd
,
(
*
rref_pointer_array
),
tables_list
,
fields_list
,
1
,
...
...
@@ -939,8 +936,10 @@ JOIN::optimize()
as in other cases the join is done before the sort.
*/
if
(
const_tables
!=
tables
&&
(
order
||
group_list
)
&&
join_tab
[
const_tables
].
type
!=
JT_ALL
&&
(
order
||
group_list
)
&&
join_tab
[
const_tables
].
type
!=
JT_ALL
&&
join_tab
[
const_tables
].
type
!=
JT_FT
&&
join_tab
[
const_tables
].
type
!=
JT_REF_OR_NULL
&&
(
order
&&
simple_order
||
group_list
&&
simple_group
))
{
if
(
add_ref_to_table_cond
(
thd
,
&
join_tab
[
const_tables
]))
...
...
@@ -1094,7 +1093,7 @@ JOIN::reinit()
if
(
unit
->
select_limit_cnt
==
HA_POS_ERROR
)
select_lex
->
options
&=
~
OPTION_FOUND_ROWS
;
if
(
setup_tables
(
tables_list
))
if
(
setup_tables
(
tables_list
,
1
))
DBUG_RETURN
(
1
);
/* Reset of sum functions */
...
...
@@ -1590,12 +1589,7 @@ JOIN::cleanup()
JOIN_TAB
*
tab
,
*
end
;
for
(
tab
=
join_tab
,
end
=
tab
+
tables
;
tab
!=
end
;
tab
++
)
{
delete
tab
->
select
;
delete
tab
->
quick
;
tab
->
select
=
0
;
tab
->
quick
=
0
;
x_free
(
tab
->
cache
.
buff
);
tab
->
cache
.
buff
=
0
;
tab
->
cleanup
();
}
}
tmp_join
->
tmp_join
=
0
;
...
...
@@ -1659,13 +1653,14 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
goto
err
;
}
}
free_join
=
0
;
}
free_join
=
0
;
join
->
select_options
=
select_options
;
}
else
{
join
=
new
JOIN
(
thd
,
fields
,
select_options
,
result
);
if
(
!
(
join
=
new
JOIN
(
thd
,
fields
,
select_options
,
result
)))
DBUG_RETURN
(
-
1
);
thd
->
proc_info
=
"init"
;
thd
->
used_tables
=
0
;
// Updated by setup_fields
if
(
join
->
prepare
(
rref_pointer_array
,
tables
,
wild_num
,
...
...
@@ -1726,8 +1721,8 @@ static ha_rows get_quick_record_count(THD *thd, SQL_SELECT *select,
{
select
->
head
=
table
;
table
->
reginfo
.
impossible_range
=
0
;
if
((
error
=
select
->
test_quick_select
(
thd
,
*
(
key_map
*
)
keys
,(
table_map
)
0
,
limit
))
==
1
)
if
((
error
=
select
->
test_quick_select
(
thd
,
*
(
key_map
*
)
keys
,(
table_map
)
0
,
limit
))
==
1
)
DBUG_RETURN
(
select
->
quick
->
records
);
if
(
error
==
-
1
)
{
...
...
@@ -2210,7 +2205,7 @@ merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end,
*/
static
void
add_key_field
(
KEY_FIELD
**
key_fields
,
uint
and_level
,
add_key_field
(
KEY_FIELD
**
key_fields
,
uint
and_level
,
COND
*
cond
,
Field
*
field
,
bool
eq_func
,
Item
**
value
,
uint
num_values
,
table_map
usable_tables
)
{
...
...
@@ -2277,6 +2272,17 @@ add_key_field(KEY_FIELD **key_fields,uint and_level,
(
*
value
)
->
result_type
()
!=
STRING_RESULT
&&
field
->
cmp_type
()
!=
(
*
value
)
->
result_type
())
return
;
/*
We can't use indexes if the effective collation
of the operation differ from the field collation.
*/
if
(
field
->
result_type
()
==
STRING_RESULT
&&
(
*
value
)
->
result_type
()
==
STRING_RESULT
&&
field
->
cmp_type
()
==
STRING_RESULT
&&
((
Field_str
*
)
field
)
->
charset
()
!=
cond
->
compare_collation
())
return
;
}
}
DBUG_ASSERT
(
num_values
==
1
);
...
...
@@ -3441,7 +3447,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
{
/* Must read with repeat */
j
->
type
=
null_ref_key
?
JT_REF_OR_NULL
:
JT_REF
;
j
->
null_ref_key
=
null_ref_key
;
j
->
ref
.
null_ref_key
=
null_ref_key
;
}
else
if
(
ref_key
==
j
->
ref
.
key_copy
)
{
...
...
@@ -3920,6 +3926,41 @@ bool error_if_full_join(JOIN *join)
}
/*
cleanup JOIN_TAB
SYNOPSIS
JOIN_TAB::cleanup()
*/
void
JOIN_TAB
::
cleanup
()
{
delete
select
;
select
=
0
;
delete
quick
;
quick
=
0
;
x_free
(
cache
.
buff
);
cache
.
buff
=
0
;
if
(
table
)
{
if
(
table
->
key_read
)
{
table
->
key_read
=
0
;
table
->
file
->
extra
(
HA_EXTRA_NO_KEYREAD
);
}
/* Don't free index if we are using read_record */
if
(
!
read_record
.
table
)
table
->
file
->
index_end
();
/*
We need to reset this for next select
(Tested in part_of_refkey)
*/
table
->
reginfo
.
join_tab
=
0
;
}
end_read_record
(
&
read_record
);
}
/*
Free resources of given join
...
...
@@ -3954,11 +3995,6 @@ JOIN::join_free(bool full)
{
if
(
tab
->
table
)
{
if
(
tab
->
table
->
key_read
)
{
tab
->
table
->
key_read
=
0
;
tab
->
table
->
file
->
extra
(
HA_EXTRA_NO_KEYREAD
);
}
/* Don't free index if we are using read_record */
if
(
!
tab
->
read_record
.
table
)
tab
->
table
->
file
->
index_end
();
...
...
@@ -3969,29 +4005,7 @@ JOIN::join_free(bool full)
{
for
(
tab
=
join_tab
,
end
=
tab
+
tables
;
tab
!=
end
;
tab
++
)
{
delete
tab
->
select
;
delete
tab
->
quick
;
tab
->
select
=
0
;
tab
->
quick
=
0
;
x_free
(
tab
->
cache
.
buff
);
tab
->
cache
.
buff
=
0
;
if
(
tab
->
table
)
{
if
(
tab
->
table
->
key_read
)
{
tab
->
table
->
key_read
=
0
;
tab
->
table
->
file
->
extra
(
HA_EXTRA_NO_KEYREAD
);
}
/* Don't free index if we are using read_record */
if
(
!
tab
->
read_record
.
table
)
tab
->
table
->
file
->
index_end
();
/*
We need to reset this for next select
(Tested in part_of_refkey)
*/
tab
->
table
->
reginfo
.
join_tab
=
0
;
}
end_read_record
(
&
tab
->
read_record
);
tab
->
cleanup
();
}
table
=
0
;
}
...
...
@@ -5237,17 +5251,9 @@ remove_eq_conds(COND *cond,Item::cond_result *cond_value)
{
Item
*
new_item
=
remove_eq_conds
(
item
,
&
tmp_cond_value
);
if
(
!
new_item
)
{
#ifdef DELETE_ITEMS
delete
item
;
// This may be shared
#endif
li
.
remove
();
}
else
if
(
item
!=
new_item
)
{
#ifdef DELETE_ITEMS
delete
item
;
// This may be shared
#endif
VOID
(
li
.
replace
(
new_item
));
should_fix_fields
=
1
;
}
...
...
@@ -6604,14 +6610,14 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
static
int
flush_cached_records
(
JOIN
*
join
,
JOIN_TAB
*
join_tab
,
bool
skip
p
_last
)
flush_cached_records
(
JOIN
*
join
,
JOIN_TAB
*
join_tab
,
bool
skip_last
)
{
int
error
;
READ_RECORD
*
info
;
if
(
!
join_tab
->
cache
.
records
)
return
0
;
/* Nothing to do */
if
(
skip
p
_last
)
if
(
skip_last
)
(
void
)
store_record_in_cache
(
&
join_tab
->
cache
);
// Must save this for later
if
(
join_tab
->
use_quick
==
2
)
{
...
...
@@ -6645,21 +6651,21 @@ flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skipp_last)
}
SQL_SELECT
*
select
=
join_tab
->
select
;
if
(
!
error
&&
(
!
join_tab
->
cache
.
select
||
!
join_tab
->
cache
.
select
->
skip
p
_record
()))
!
join_tab
->
cache
.
select
->
skip_record
()))
{
uint
i
;
reset_cache
(
&
join_tab
->
cache
);
for
(
i
=
(
join_tab
->
cache
.
records
-
(
skip
p
_last
?
1
:
0
))
;
i
--
>
0
;)
for
(
i
=
(
join_tab
->
cache
.
records
-
(
skip_last
?
1
:
0
))
;
i
--
>
0
;)
{
read_cached_record
(
join_tab
);
if
(
!
select
||
!
select
->
skip
p
_record
())
if
(
!
select
||
!
select
->
skip_record
())
if
((
error
=
(
join_tab
->
next_select
)(
join
,
join_tab
+
1
,
0
))
<
0
)
return
error
;
/* purecov: inspected */
}
}
}
while
(
!
(
error
=
info
->
read_record
(
info
)));
if
(
skip
p
_last
)
if
(
skip_last
)
read_cached_record
(
join_tab
);
// Restore current record
reset_cache
(
&
join_tab
->
cache
);
join_tab
->
cache
.
records
=
0
;
join_tab
->
cache
.
ptr_record
=
(
uint
)
~
0
;
...
...
@@ -7066,12 +7072,12 @@ join_read_always_key_or_null(JOIN_TAB *tab)
int
res
;
/* First read according to key which is NOT NULL */
*
tab
->
null_ref_key
=
0
;
*
tab
->
ref
.
null_ref_key
=
0
;
// Clear null byte
if
((
res
=
join_read_always_key
(
tab
))
>=
0
)
return
res
;
/* Then read key with null value */
*
tab
->
null_ref_key
=
1
;
*
tab
->
ref
.
null_ref_key
=
1
;
// Set null byte
return
safe_index_read
(
tab
);
}
...
...
@@ -7085,10 +7091,10 @@ join_read_next_same_or_null(READ_RECORD *info)
JOIN_TAB
*
tab
=
info
->
table
->
reginfo
.
join_tab
;
/* Test if we have already done a read after null key */
if
(
*
tab
->
null_ref_key
)
if
(
*
tab
->
ref
.
null_ref_key
)
return
-
1
;
// All keys read
*
tab
->
null_ref_key
=
1
;
// Read null key
return
safe_index_read
(
tab
);
*
tab
->
ref
.
null_ref_key
=
1
;
// Set null byte
return
safe_index_read
(
tab
);
// then read null keys
}
...
...
@@ -8061,8 +8067,9 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
For impossible ranges (like when doing a lookup on NULL on a NOT NULL
field, quick will contain an empty record set.
*/
if
(
!
(
select
->
quick
=
get_ft_or_quick_select_for_ref
(
tab
->
join
->
thd
,
table
,
tab
)))
if
(
!
(
select
->
quick
=
tab
->
type
==
JT_FT
?
new
FT_SELECT
(
thd
,
table
,
tab
->
ref
.
key
)
:
get_quick_select_for_ref
(
thd
,
table
,
&
tab
->
ref
)))
goto
err
;
}
}
...
...
@@ -8070,9 +8077,12 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
table
->
file
->
info
(
HA_STATUS_VARIABLE
);
// Get record count
table
->
sort
.
found_records
=
filesort
(
thd
,
table
,
sortorder
,
length
,
select
,
filesort_limit
,
&
examined_rows
);
tab
->
records
=
table
->
sort
.
found_records
;
// For SQL_CALC_ROWS
delete
select
;
// filesort did select
tab
->
select
=
0
;
tab
->
records
=
table
->
sort
.
found_records
;
// For SQL_CALC_ROWS
if
(
select
)
{
select
->
cleanup
();
// filesort did select
tab
->
select
=
0
;
}
tab
->
select_cond
=
0
;
tab
->
type
=
JT_ALL
;
// Read with normal read_record
tab
->
read_first_record
=
join_init_read_record
;
...
...
@@ -9155,7 +9165,7 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
if
(
pos
->
type
()
==
Item
::
FIELD_ITEM
)
{
Item_field
*
item
;
if
(
!
(
item
=
new
Item_field
(
thd
,
*
((
Item_field
*
)
pos
))))
if
(
!
(
item
=
new
Item_field
(
thd
,
((
Item_field
*
)
pos
))))
goto
err
;
pos
=
item
;
if
(
item
->
field
->
flags
&
BLOB_FLAG
)
...
...
@@ -10056,20 +10066,23 @@ int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
sl
;
sl
=
sl
->
next_select
())
{
// drop UNCACHEABLE_EXPLAIN, because it is for internal usage only
uint8
uncacheable
=
(
sl
->
uncacheable
&
~
UNCACHEABLE_EXPLAIN
);
res
=
mysql_explain_select
(
thd
,
sl
,
(((
&
thd
->
lex
->
select_lex
)
==
sl
)
?
((
thd
->
lex
->
all_selects_list
!=
sl
)
?
"PRIMARY"
:
"SIMPLE"
)
:
((
thd
->
lex
->
all_selects_list
!=
sl
)
?
primary_key_name
:
"SIMPLE"
)
:
((
sl
==
first
)
?
((
sl
->
linkage
==
DERIVED_TABLE_TYPE
)
?
"DERIVED"
:
((
sl
->
uncacheable
&
UNCACHEABLE_DEPENDENT
)
?
((
uncacheable
&
UNCACHEABLE_DEPENDENT
)
?
"DEPENDENT SUBQUERY"
:
(
sl
->
uncacheable
?
"UNCACHEABLE SUBQUERY"
:
(
uncacheable
?
"UNCACHEABLE SUBQUERY"
:
"SUBQUERY"
)))
:
((
sl
->
uncacheable
&
UNCACHEABLE_DEPENDENT
)
?
((
uncacheable
&
UNCACHEABLE_DEPENDENT
)
?
"DEPENDENT UNION"
:
sl
->
uncacheable
?
"UNCACHEABLE UNION"
:
uncacheable
?
"UNCACHEABLE UNION"
:
"UNION"
))),
result
);
if
(
res
)
...
...
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