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
d24a2296
Commit
d24a2296
authored
Feb 19, 2004
by
igor@rurik.mysql.com
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Manual merge
parent
f18e0068
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 @
d24a2296
...
...
@@ -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 @
d24a2296
...
...
@@ -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 @
d24a2296
...
...
@@ -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