Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
mariadb
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
mariadb
Commits
cd6bf73f
Commit
cd6bf73f
authored
Nov 07, 2002
by
serg@sergbook.mysql.com
Browse files
Options
Browse Files
Download
Plain Diff
manually merged
parents
d4cd3852
7ad5882d
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
1131 additions
and
495 deletions
+1131
-495
Docs/manual.texi
Docs/manual.texi
+7
-0
dbug/dbug_add_tags.pl
dbug/dbug_add_tags.pl
+73
-0
myisam/ft_nlq_search.c
myisam/ft_nlq_search.c
+2
-1
mysql-test/r/func_time.result
mysql-test/r/func_time.result
+1
-0
mysql-test/r/merge.result
mysql-test/r/merge.result
+20
-0
mysql-test/t/merge.test
mysql-test/t/merge.test
+19
-0
sql/ha_myisam.cc
sql/ha_myisam.cc
+166
-79
sql/ha_myisammrg.cc
sql/ha_myisammrg.cc
+99
-27
sql/handler.cc
sql/handler.cc
+95
-36
sql/item_cmpfunc.cc
sql/item_cmpfunc.cc
+9
-3
sql/mysqld.cc
sql/mysqld.cc
+4
-0
sql/opt_range.cc
sql/opt_range.cc
+234
-116
sql/sql_select.cc
sql/sql_select.cc
+401
-232
sql/stacktrace.c
sql/stacktrace.c
+1
-1
No files found.
Docs/manual.texi
View file @
cd6bf73f
...
...
@@ -51774,6 +51774,8 @@ not yet 100% confident in this code.
Allow one to start multiple MySQL servers on windows (code backported
from 4.0.2).
@item
Fixed that @code{--core-file} works on Linux (at least on kernel 2.4.18).
@item
Fixed a problem with BDB and @code{ALTER TABLE}.
@item
Fixed reference to freed memory when doing complicated @code{GROUP BY
...
...
@@ -51859,6 +51861,11 @@ Changed initialisation of @code{RND()} to make it less predicatable.
Fixed problem with @code{GROUP BY} on result with expression that created a
@code{BLOB} field.
@item
Fixed problem with @code{GROUP BY} on columns that have NULL values. To
solve this we now create an MyISAM temporary table when doing a group by
on a possible NULL item. In MySQL 4.0.5 we can again use in memory HEAP
tables for this case.
@item
Fixed problem with privilege tables when downgrading from 4.0.2 to 3.23.
@item
Fixed thread bug in @code{SLAVE START}, @code{SLAVE STOP} and automatic repair
dbug/dbug_add_tags.pl
0 → 100755
View file @
cd6bf73f
#!/usr/bin/perl
die
"
No files specified
\n
"
unless
$ARGV
[
0
];
$ctags
=
"
exctags -x -f - --c-types=f -u
";
sub
get_tag
{
local
$.
;
local
$_
=<
TAGS
>
;
(
$symbol
,
$line
)
=
/^(.*\S)\s+function\s+(\d+)/
;
$symbol
=
$1
if
/\s(\S+)\s*\(/
;
$line
=
1e50
unless
$line
;
}
while
(
$src
=
shift
)
{
warn
"
==>
$src
\n
";
$dst
=
$src
.
$$
;
open
(
TAGS
,
"
$ctags
$src
|
")
||
die
"
Cannot exec('
$ctags
$src
'): $!
";
open
(
SRC
,
"
<
$src
")
||
die
"
Cannot open
$src
: $!
";
open
(
DST
,
"
>
$dst
")
||
die
"
Cannot create
$dst
: $!
";
select
DST
;
&
get_tag
;
$in_func
=
0
;
while
(
<
SRC
>
)
{
my
$orig
=
$_
;
if
(
$in_func
)
{
if
(
/\breturn\b/
&&
!
/\/\*.*\breturn\b.*\*\//
&&
!
/;/
)
{
$_
.=<
SRC
>
until
/;/
;
}
s/(?<=\s)return\s*;/DBUG_VOID_RETURN;/
;
s/(?<=\s)return\s*(.+)\s*;/DBUG_RETURN(\1);/s
;
$ret_line
=
$.
if
/DBUG_(VOID_)?RETURN/
;
#{{
print
"
$tab
DBUG_VOID_RETURN;
\n
"
if
/^$tab}/
&&
$ret_line
<
$.
-
1
;
$in_func
=
0
if
/^$tab}/
;
warn
"
$src
:
"
.
(
$.
-
1
)
.
"
\t
$orig
"
if
/\breturn\b/
;
}
print
;
next
if
$.
<
$line
;
die
"
Something wrong:
\
$.=$.,
\
$line
=
$line
,
\
$symbol
=
$symbol
\n
"
if
$.
>
$line
;
&
get_tag
&&
next
if
/^\s*inline /
;
print
$_
=<
SRC
>
until
/{/
;
$tab
=
$`
;
&
get_tag
&&
next
if
/}/
;
# skip one-liners
$semicolon
=
1
;
while
(
<
SRC
>
)
{
$skip
=!
$semicolon
;
$semicolon
=
/;\s*$/
;
print
&&
next
if
$skip
||
(
/^\s+\w+((::\w+)?|<\w+>)\s+\**\w+/
&&
!
/^\s*return/
);
last
if
/DBUG_ENTER/
;
print
"
$tab
DBUG_ENTER(
\"
$symbol
\"
);
\n
";
print
"
\n
"
unless
$_
eq
"
\n
";
last
;
}
$in_func
=
1
;
&
get_tag
;
redo
;
}
close
SRC
;
close
DST
;
close
TAGS
;
unlink
("
$src
.orig
");
rename
(
$src
,
"
$src
.orig
")
||
die
"
Cannot rename
$src
to
$src
.orig: $!
";
rename
(
$dst
,
$src
)
||
die
"
Cannot rename
$dst
to
$src
: $!
";
}
warn
"
All done!
\n
";
myisam/ft_nlq_search.c
View file @
cd6bf73f
...
...
@@ -154,7 +154,8 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio)
if
(
doc_cnt
)
{
word
->
weight
*=
GWS_IN_USE
;
if
(
word
->
weight
<
0
)
word
->
weight
=
0
;
if
(
word
->
weight
<
0
)
word
->
weight
=
0
;
}
DBUG_RETURN
(
0
);
...
...
mysql-test/r/func_time.result
View file @
cd6bf73f
...
...
@@ -380,6 +380,7 @@ CREATE TABLE t3 (ctime1 char(19) NOT NULL, ctime2 char(19) NOT NULL);
INSERT INTO t3 VALUES ("2002-10-29 16:51:06","2002-11-05 16:47:31");
select * from t1, t2 where t1.start between t2.ctime1 and t2.ctime2;
start ctime1 ctime2
2002-11-04 00:00:00 20021029165106 20021105164731
select * from t1, t2 where t1.start >= t2.ctime1 and t1.start <= t2.ctime2;
start ctime1 ctime2
2002-11-04 00:00:00 20021029165106 20021105164731
...
...
mysql-test/r/merge.result
View file @
cd6bf73f
...
...
@@ -541,3 +541,23 @@ select max(b) from t1 where a = 2;
max(b)
1
drop table if exists t,t1,t2;
drop table if exists t1, t2, t3, t4, t5, t6;
create table t1 (a int not null);
create table t2 (a int not null);
insert into t1 values (1);
insert into t2 values (2);
create temporary table t3 (a int not null) TYPE=MERGE UNION=(t1,t2);
select * from t3;
a
1
2
create temporary table t4 (a int not null);
create temporary table t5 (a int not null);
insert into t4 values (1);
insert into t5 values (2);
create temporary table t6 (a int not null) TYPE=MERGE UNION=(t4,t5);
select * from t6;
a
1
2
drop table if exists t1, t2, t3, t4, t5, t6;
mysql-test/t/merge.test
View file @
cd6bf73f
...
...
@@ -185,3 +185,22 @@ CREATE TABLE t ( a int(11) NOT NULL default '0', b int(11) NOT NULL default '0
select
max
(
b
)
from
t
where
a
=
2
;
select
max
(
b
)
from
t1
where
a
=
2
;
drop
table
if
exists
t
,
t1
,
t2
;
#
# temporary merge tables
#
drop
table
if
exists
t1
,
t2
,
t3
,
t4
,
t5
,
t6
;
create
table
t1
(
a
int
not
null
);
create
table
t2
(
a
int
not
null
);
insert
into
t1
values
(
1
);
insert
into
t2
values
(
2
);
create
temporary
table
t3
(
a
int
not
null
)
TYPE
=
MERGE
UNION
=
(
t1
,
t2
);
select
*
from
t3
;
create
temporary
table
t4
(
a
int
not
null
);
create
temporary
table
t5
(
a
int
not
null
);
insert
into
t4
values
(
1
);
insert
into
t5
values
(
2
);
create
temporary
table
t6
(
a
int
not
null
)
TYPE
=
MERGE
UNION
=
(
t4
,
t5
);
select
*
from
t6
;
drop
table
if
exists
t1
,
t2
,
t3
,
t4
,
t5
,
t6
;
sql/ha_myisam.cc
View file @
cd6bf73f
...
...
@@ -48,6 +48,8 @@ TYPELIB myisam_recover_typelib= {array_elements(myisam_recover_names)-1,"",
static
void
mi_check_print_msg
(
MI_CHECK
*
param
,
const
char
*
msg_type
,
const
char
*
fmt
,
va_list
args
)
{
DBUG_ENTER
(
"mi_check_print_msg"
);
THD
*
thd
=
(
THD
*
)
param
->
thd
;
String
*
packet
=
&
thd
->
packet
;
uint
length
;
...
...
@@ -64,12 +66,12 @@ static void mi_check_print_msg(MI_CHECK *param, const char* msg_type,
if
(
thd
->
net
.
vio
==
0
)
{
sql_print_error
(
msgbuf
);
return
;
DBUG_VOID_RETURN
;
}
if
(
param
->
testflag
&
(
T_CREATE_MISSING_KEYS
|
T_SAFE_REPAIR
|
T_AUTO_REPAIR
))
{
my_message
(
ER_NOT_KEYFILE
,
msgbuf
,
MYF
(
MY_WME
));
return
;
DBUG_VOID_RETURN
;
}
length
=
(
uint
)
(
strxmov
(
name
,
param
->
db_name
,
"."
,
param
->
table_name
,
NullS
)
-
name
);
...
...
@@ -81,37 +83,46 @@ static void mi_check_print_msg(MI_CHECK *param, const char* msg_type,
if
(
my_net_write
(
&
thd
->
net
,
(
char
*
)
thd
->
packet
.
ptr
(),
thd
->
packet
.
length
()))
sql_print_error
(
"Failed on my_net_write, writing to stderr instead: %s
\n
"
,
msgbuf
);
return
;
DBUG_VOID_RETURN
;
}
extern
"C"
{
void
mi_check_print_error
(
MI_CHECK
*
param
,
const
char
*
fmt
,...)
{
DBUG_ENTER
(
"mi_check_print_error"
);
param
->
error_printed
|=
1
;
param
->
out_flag
|=
O_DATA_LOST
;
va_list
args
;
va_start
(
args
,
fmt
);
mi_check_print_msg
(
param
,
"error"
,
fmt
,
args
);
va_end
(
args
);
DBUG_VOID_RETURN
;
}
void
mi_check_print_info
(
MI_CHECK
*
param
,
const
char
*
fmt
,...)
{
va_list
args
;
DBUG_ENTER
(
"mi_check_print_info"
);
va_start
(
args
,
fmt
);
mi_check_print_msg
(
param
,
"info"
,
fmt
,
args
);
va_end
(
args
);
DBUG_VOID_RETURN
;
}
void
mi_check_print_warning
(
MI_CHECK
*
param
,
const
char
*
fmt
,...)
{
DBUG_ENTER
(
"mi_check_print_warning"
);
param
->
warning_printed
=
1
;
param
->
out_flag
|=
O_DATA_LOST
;
va_list
args
;
va_start
(
args
,
fmt
);
mi_check_print_msg
(
param
,
"warning"
,
fmt
,
args
);
va_end
(
args
);
DBUG_VOID_RETURN
;
}
}
...
...
@@ -122,15 +133,18 @@ const char **ha_myisam::bas_ext() const
const
char
*
ha_myisam
::
index_type
(
uint
key_number
)
{
return
((
table
->
key_info
[
key_number
].
flags
&
HA_FULLTEXT
)
?
DBUG_ENTER
(
"*ha_myisam::index_type"
);
DBUG_RETURN
(((
table
->
key_info
[
key_number
].
flags
&
HA_FULLTEXT
)
?
"FULLTEXT"
:
"BTREE"
);
"BTREE"
)
)
;
}
int
ha_myisam
::
net_read_dump
(
NET
*
net
)
{
int
data_fd
=
file
->
dfile
;
int
error
=
0
;
DBUG_ENTER
(
"ha_myisam::net_read_dump"
);
my_seek
(
data_fd
,
0L
,
MY_SEEK_SET
,
MYF
(
MY_WME
));
for
(;;)
...
...
@@ -153,12 +167,14 @@ int ha_myisam::net_read_dump(NET* net)
}
err:
return
error
;
DBUG_RETURN
(
error
)
;
}
int
ha_myisam
::
dump
(
THD
*
thd
,
int
fd
)
{
DBUG_ENTER
(
"ha_myisam::dump"
);
MYISAM_SHARE
*
share
=
file
->
s
;
NET
*
net
=
&
thd
->
net
;
uint
blocksize
=
share
->
blocksize
;
...
...
@@ -166,7 +182,7 @@ int ha_myisam::dump(THD* thd, int fd)
int
data_fd
=
file
->
dfile
;
byte
*
buf
=
(
byte
*
)
my_malloc
(
blocksize
,
MYF
(
MY_WME
));
if
(
!
buf
)
return
ENOMEM
;
DBUG_RETURN
(
ENOMEM
)
;
int
error
=
0
;
my_seek
(
data_fd
,
0L
,
MY_SEEK_SET
,
MYF
(
MY_WME
));
...
...
@@ -206,15 +222,17 @@ int ha_myisam::dump(THD* thd, int fd)
err:
my_free
((
gptr
)
buf
,
MYF
(
0
));
return
error
;
DBUG_RETURN
(
error
)
;
}
/* Name is here without an extension */
int
ha_myisam
::
open
(
const
char
*
name
,
int
mode
,
uint
test_if_locked
)
{
DBUG_ENTER
(
"ha_myisam::open"
);
if
(
!
(
file
=
mi_open
(
name
,
mode
,
test_if_locked
)))
return
(
my_errno
?
my_errno
:
-
1
);
DBUG_RETURN
((
my_errno
?
my_errno
:
-
1
)
);
if
(
test_if_locked
&
(
HA_OPEN_IGNORE_IF_LOCKED
|
HA_OPEN_TMP_TABLE
))
VOID
(
mi_extra
(
file
,
HA_EXTRA_NO_WAIT_LOCK
,
0
));
...
...
@@ -223,18 +241,22 @@ int ha_myisam::open(const char *name, int mode, uint test_if_locked)
VOID
(
mi_extra
(
file
,
HA_EXTRA_WAIT_LOCK
,
0
));
if
(
!
table
->
db_record_offset
)
int_table_flags
|=
HA_REC_NOT_IN_SEQ
;
return
(
0
);
DBUG_RETURN
((
0
)
);
}
int
ha_myisam
::
close
(
void
)
{
MI_INFO
*
tmp
=
file
;
DBUG_ENTER
(
"ha_myisam::close"
);
file
=
0
;
return
mi_close
(
tmp
);
DBUG_RETURN
(
mi_close
(
tmp
)
);
}
int
ha_myisam
::
write_row
(
byte
*
buf
)
{
DBUG_ENTER
(
"ha_myisam::write_row"
);
statistic_increment
(
ha_write_count
,
&
LOCK_status
);
/* If we have a timestamp column, update it to the current time */
...
...
@@ -248,12 +270,14 @@ int ha_myisam::write_row(byte * buf)
*/
if
(
table
->
next_number_field
&&
buf
==
table
->
record
[
0
])
update_auto_increment
();
return
mi_write
(
file
,
buf
);
DBUG_RETURN
(
mi_write
(
file
,
buf
)
);
}
int
ha_myisam
::
check
(
THD
*
thd
,
HA_CHECK_OPT
*
check_opt
)
{
if
(
!
file
)
return
HA_ADMIN_INTERNAL_ERROR
;
DBUG_ENTER
(
"ha_myisam::check"
);
if
(
!
file
)
DBUG_RETURN
(
HA_ADMIN_INTERNAL_ERROR
);
int
error
;
MI_CHECK
param
;
MYISAM_SHARE
*
share
=
file
->
s
;
...
...
@@ -278,7 +302,7 @@ int ha_myisam::check(THD* thd, HA_CHECK_OPT* check_opt)
share
->
state
.
open_count
==
0
)
||
((
param
.
testflag
&
T_FAST
)
&&
(
share
->
state
.
open_count
==
(
uint
)
(
share
->
global_changed
?
1
:
0
)))))
return
HA_ADMIN_ALREADY_DONE
;
DBUG_RETURN
(
HA_ADMIN_ALREADY_DONE
)
;
error
=
chk_status
(
&
param
,
file
);
// Not fatal
error
=
chk_size
(
&
param
,
file
);
...
...
@@ -331,7 +355,7 @@ int ha_myisam::check(THD* thd, HA_CHECK_OPT* check_opt)
}
thd
->
proc_info
=
old_proc_info
;
return
error
?
HA_ADMIN_CORRUPT
:
HA_ADMIN_OK
;
DBUG_RETURN
(
error
?
HA_ADMIN_CORRUPT
:
HA_ADMIN_OK
)
;
}
...
...
@@ -345,6 +369,8 @@ int ha_myisam::analyze(THD *thd, HA_CHECK_OPT* check_opt)
{
int
error
=
0
;
MI_CHECK
param
;
DBUG_ENTER
(
"ha_myisam::analyze"
);
MYISAM_SHARE
*
share
=
file
->
s
;
myisamchk_init
(
&
param
);
...
...
@@ -357,7 +383,7 @@ int ha_myisam::analyze(THD *thd, HA_CHECK_OPT* check_opt)
param
.
using_global_keycache
=
1
;
if
(
!
(
share
->
state
.
changed
&
STATE_NOT_ANALYZED
))
return
HA_ADMIN_ALREADY_DONE
;
DBUG_RETURN
(
HA_ADMIN_ALREADY_DONE
)
;
error
=
chk_key
(
&
param
,
file
);
if
(
!
error
)
...
...
@@ -368,7 +394,7 @@ int ha_myisam::analyze(THD *thd, HA_CHECK_OPT* check_opt)
}
else
if
(
!
mi_is_crashed
(
file
))
mi_mark_crashed
(
file
);
return
error
?
HA_ADMIN_CORRUPT
:
HA_ADMIN_OK
;
DBUG_RETURN
(
error
?
HA_ADMIN_CORRUPT
:
HA_ADMIN_OK
)
;
}
...
...
@@ -380,7 +406,7 @@ int ha_myisam::restore(THD* thd, HA_CHECK_OPT *check_opt)
char
*
table_name
=
table
->
real_name
;
int
error
;
const
char
*
errmsg
;
DBUG_ENTER
(
"restore"
);
DBUG_ENTER
(
"
ha_myisam::
restore"
);
if
(
fn_format_relative_to_data_home
(
src_path
,
table_name
,
backup_dir
,
MI_NAME_DEXT
))
...
...
@@ -399,17 +425,15 @@ int ha_myisam::restore(THD* thd, HA_CHECK_OPT *check_opt)
DBUG_RETURN
(
repair
(
thd
,
&
tmp_check_opt
));
err:
{
MI_CHECK
param
;
myisamchk_init
(
&
param
);
param
.
thd
=
thd
;
param
.
op_name
=
(
char
*
)
"restore"
;
param
.
db_name
=
table
->
table_cache_key
;
param
.
table_name
=
table
->
table_name
;
param
.
testflag
=
0
;
mi_check_print_error
(
&
param
,
errmsg
,
my_errno
);
DBUG_RETURN
(
error
);
}
MI_CHECK
param
;
myisamchk_init
(
&
param
);
param
.
thd
=
thd
;
param
.
op_name
=
(
char
*
)
"restore"
;
param
.
db_name
=
table
->
table_cache_key
;
param
.
table_name
=
table
->
table_name
;
param
.
testflag
=
0
;
mi_check_print_error
(
&
param
,
errmsg
,
my_errno
);
DBUG_RETURN
(
error
);
}
...
...
@@ -460,17 +484,15 @@ int ha_myisam::backup(THD* thd, HA_CHECK_OPT *check_opt)
DBUG_RETURN
(
HA_ADMIN_OK
);
err:
{
MI_CHECK
param
;
myisamchk_init
(
&
param
);
param
.
thd
=
thd
;
param
.
op_name
=
(
char
*
)
"backup"
;
param
.
db_name
=
table
->
table_cache_key
;
param
.
table_name
=
table
->
table_name
;
param
.
testflag
=
0
;
mi_check_print_error
(
&
param
,
errmsg
,
my_errno
);
DBUG_RETURN
(
error
);
}
MI_CHECK
param
;
myisamchk_init
(
&
param
);
param
.
thd
=
thd
;
param
.
op_name
=
(
char
*
)
"backup"
;
param
.
db_name
=
table
->
table_cache_key
;
param
.
table_name
=
table
->
table_name
;
param
.
testflag
=
0
;
mi_check_print_error
(
&
param
,
errmsg
,
my_errno
);
DBUG_RETURN
(
error
);
}
...
...
@@ -479,8 +501,9 @@ int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt)
int
error
;
MI_CHECK
param
;
ha_rows
start_records
;
DBUG_ENTER
(
"ha_myisam::repair"
);
if
(
!
file
)
return
HA_ADMIN_INTERNAL_ERROR
;
if
(
!
file
)
DBUG_RETURN
(
HA_ADMIN_INTERNAL_ERROR
)
;
myisamchk_init
(
&
param
);
param
.
thd
=
thd
;
...
...
@@ -520,12 +543,14 @@ int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt)
llstr
(
start_records
,
llbuff2
),
table
->
path
);
}
return
error
;
DBUG_RETURN
(
error
)
;
}
int
ha_myisam
::
optimize
(
THD
*
thd
,
HA_CHECK_OPT
*
check_opt
)
{
if
(
!
file
)
return
HA_ADMIN_INTERNAL_ERROR
;
DBUG_ENTER
(
"ha_myisam::optimize"
);
if
(
!
file
)
DBUG_RETURN
(
HA_ADMIN_INTERNAL_ERROR
);
MI_CHECK
param
;
myisamchk_init
(
&
param
);
...
...
@@ -534,7 +559,7 @@ int ha_myisam::optimize(THD* thd, HA_CHECK_OPT *check_opt)
param
.
testflag
=
(
check_opt
->
flags
|
T_SILENT
|
T_FORCE_CREATE
|
T_REP_BY_SORT
|
T_STATISTICS
|
T_SORT_INDEX
);
param
.
sort_buffer_length
=
check_opt
->
sort_buffer_size
;
return
repair
(
thd
,
param
,
1
);
DBUG_RETURN
(
repair
(
thd
,
param
,
1
)
);
}
...
...
@@ -669,6 +694,8 @@ int ha_myisam::repair(THD *thd, MI_CHECK ¶m, bool optimize)
void
ha_myisam
::
deactivate_non_unique_index
(
ha_rows
rows
)
{
DBUG_ENTER
(
"ha_myisam::deactivate_non_unique_index"
);
MYISAM_SHARE
*
share
=
file
->
s
;
if
(
share
->
state
.
key_map
==
((
ulonglong
)
1L
<<
share
->
base
.
keys
)
-
1
)
{
...
...
@@ -690,6 +717,7 @@ void ha_myisam::deactivate_non_unique_index(ha_rows rows)
}
else
enable_activate_all_index
=
0
;
DBUG_VOID_RETURN
;
}
...
...
@@ -698,7 +726,7 @@ bool ha_myisam::activate_all_index(THD *thd)
int
error
=
0
;
MI_CHECK
param
;
MYISAM_SHARE
*
share
=
file
->
s
;
DBUG_ENTER
(
"activate_all_index"
);
DBUG_ENTER
(
"
ha_myisam::
activate_all_index"
);
mi_extra
(
file
,
HA_EXTRA_BULK_INSERT_END
,
0
);
table
->
bulk_insert
=
0
;
...
...
@@ -752,131 +780,165 @@ bool ha_myisam::check_and_repair(THD *thd)
bool
ha_myisam
::
is_crashed
()
const
{
return
(
file
->
s
->
state
.
changed
&
STATE_CRASHED
||
(
my_disable_locking
&&
file
->
s
->
state
.
open_count
));
DBUG_ENTER
(
"ha_myisam::is_crashed"
);
DBUG_RETURN
((
file
->
s
->
state
.
changed
&
STATE_CRASHED
||
(
my_disable_locking
&&
file
->
s
->
state
.
open_count
)));
}
int
ha_myisam
::
update_row
(
const
byte
*
old_data
,
byte
*
new_data
)
{
DBUG_ENTER
(
"ha_myisam::update_row"
);
statistic_increment
(
ha_update_count
,
&
LOCK_status
);
if
(
table
->
time_stamp
)
update_timestamp
(
new_data
+
table
->
time_stamp
-
1
);
return
mi_update
(
file
,
old_data
,
new_data
);
DBUG_RETURN
(
mi_update
(
file
,
old_data
,
new_data
)
);
}
int
ha_myisam
::
delete_row
(
const
byte
*
buf
)
{
DBUG_ENTER
(
"ha_myisam::delete_row"
);
statistic_increment
(
ha_delete_count
,
&
LOCK_status
);
return
mi_delete
(
file
,
buf
);
DBUG_RETURN
(
mi_delete
(
file
,
buf
)
);
}
int
ha_myisam
::
index_read
(
byte
*
buf
,
const
byte
*
key
,
uint
key_len
,
enum
ha_rkey_function
find_flag
)
{
DBUG_ENTER
(
"ha_myisam::index_read"
);
statistic_increment
(
ha_read_key_count
,
&
LOCK_status
);
int
error
=
mi_rkey
(
file
,
buf
,
active_index
,
key
,
key_len
,
find_flag
);
table
->
status
=
error
?
STATUS_NOT_FOUND
:
0
;
return
error
;
DBUG_RETURN
(
error
)
;
}
int
ha_myisam
::
index_read_idx
(
byte
*
buf
,
uint
index
,
const
byte
*
key
,
uint
key_len
,
enum
ha_rkey_function
find_flag
)
{
DBUG_ENTER
(
"ha_myisam::index_read_idx"
);
statistic_increment
(
ha_read_key_count
,
&
LOCK_status
);
int
error
=
mi_rkey
(
file
,
buf
,
index
,
key
,
key_len
,
find_flag
);
table
->
status
=
error
?
STATUS_NOT_FOUND
:
0
;
return
error
;
DBUG_RETURN
(
error
)
;
}
int
ha_myisam
::
index_read_last
(
byte
*
buf
,
const
byte
*
key
,
uint
key_len
)
{
DBUG_ENTER
(
"ha_myisam::index_read_last"
);
statistic_increment
(
ha_read_key_count
,
&
LOCK_status
);
int
error
=
mi_rkey
(
file
,
buf
,
active_index
,
key
,
key_len
,
HA_READ_PREFIX_LAST
);
table
->
status
=
error
?
STATUS_NOT_FOUND
:
0
;
return
error
;
DBUG_RETURN
(
error
)
;
}
int
ha_myisam
::
index_next
(
byte
*
buf
)
{
DBUG_ENTER
(
"ha_myisam::index_next"
);
statistic_increment
(
ha_read_next_count
,
&
LOCK_status
);
int
error
=
mi_rnext
(
file
,
buf
,
active_index
);
table
->
status
=
error
?
STATUS_NOT_FOUND
:
0
;
return
error
;
DBUG_RETURN
(
error
)
;
}
int
ha_myisam
::
index_prev
(
byte
*
buf
)
{
DBUG_ENTER
(
"ha_myisam::index_prev"
);
statistic_increment
(
ha_read_prev_count
,
&
LOCK_status
);
int
error
=
mi_rprev
(
file
,
buf
,
active_index
);
table
->
status
=
error
?
STATUS_NOT_FOUND
:
0
;
return
error
;
DBUG_RETURN
(
error
)
;
}
int
ha_myisam
::
index_first
(
byte
*
buf
)
{
DBUG_ENTER
(
"ha_myisam::index_first"
);
statistic_increment
(
ha_read_first_count
,
&
LOCK_status
);
int
error
=
mi_rfirst
(
file
,
buf
,
active_index
);
table
->
status
=
error
?
STATUS_NOT_FOUND
:
0
;
return
error
;
DBUG_RETURN
(
error
)
;
}
int
ha_myisam
::
index_last
(
byte
*
buf
)
{
DBUG_ENTER
(
"ha_myisam::index_last"
);
statistic_increment
(
ha_read_last_count
,
&
LOCK_status
);
int
error
=
mi_rlast
(
file
,
buf
,
active_index
);
table
->
status
=
error
?
STATUS_NOT_FOUND
:
0
;
return
error
;
DBUG_RETURN
(
error
)
;
}
int
ha_myisam
::
index_next_same
(
byte
*
buf
,
const
byte
*
key
__attribute__
((
unused
)),
uint
length
__attribute__
((
unused
)))
{
DBUG_ENTER
(
"ha_myisam::index_next_same"
);
statistic_increment
(
ha_read_next_count
,
&
LOCK_status
);
int
error
=
mi_rnext_same
(
file
,
buf
);
table
->
status
=
error
?
STATUS_NOT_FOUND
:
0
;
return
error
;
DBUG_RETURN
(
error
)
;
}
int
ha_myisam
::
rnd_init
(
bool
scan
)
{
DBUG_ENTER
(
"ha_myisam::rnd_init"
);
if
(
scan
)
return
mi_scan_init
(
file
);
return
mi_extra
(
file
,
HA_EXTRA_RESET
,
0
);
DBUG_RETURN
(
mi_scan_init
(
file
)
);
DBUG_RETURN
(
mi_extra
(
file
,
HA_EXTRA_RESET
,
0
)
);
}
int
ha_myisam
::
rnd_next
(
byte
*
buf
)
{
DBUG_ENTER
(
"ha_myisam::rnd_next"
);
statistic_increment
(
ha_read_rnd_next_count
,
&
LOCK_status
);
int
error
=
mi_scan
(
file
,
buf
);
table
->
status
=
error
?
STATUS_NOT_FOUND
:
0
;
return
error
;
DBUG_RETURN
(
error
)
;
}
int
ha_myisam
::
restart_rnd_next
(
byte
*
buf
,
byte
*
pos
)
{
return
rnd_pos
(
buf
,
pos
);
DBUG_ENTER
(
"ha_myisam::restart_rnd_next"
);
DBUG_RETURN
(
rnd_pos
(
buf
,
pos
));
}
int
ha_myisam
::
rnd_pos
(
byte
*
buf
,
byte
*
pos
)
{
DBUG_ENTER
(
"ha_myisam::rnd_pos"
);
statistic_increment
(
ha_read_rnd_count
,
&
LOCK_status
);
int
error
=
mi_rrnd
(
file
,
buf
,
ha_get_ptr
(
pos
,
ref_length
));
table
->
status
=
error
?
STATUS_NOT_FOUND
:
0
;
return
error
;
DBUG_RETURN
(
error
)
;
}
void
ha_myisam
::
position
(
const
byte
*
record
)
{
my_off_t
position
=
mi_position
(
file
);
DBUG_ENTER
(
"ha_myisam::position"
);
ha_store_ptr
(
ref
,
ref_length
,
position
);
DBUG_VOID_RETURN
;
}
void
ha_myisam
::
info
(
uint
flag
)
{
MI_ISAMINFO
info
;
char
name_buff
[
FN_REFLEN
];
DBUG_ENTER
(
"ha_myisam::info"
);
(
void
)
mi_status
(
file
,
&
info
,
flag
);
if
(
flag
&
HA_STATUS_VARIABLE
)
...
...
@@ -930,14 +992,17 @@ void ha_myisam::info(uint flag)
update_time
=
info
.
update_time
;
if
(
flag
&
HA_STATUS_AUTO
)
auto_increment_value
=
info
.
auto_increment
;
DBUG_VOID_RETURN
;
}
int
ha_myisam
::
extra
(
enum
ha_extra_function
operation
)
{
DBUG_ENTER
(
"ha_myisam::extra"
);
if
((
specialflag
&
SPECIAL_SAFE_MODE
)
&&
operation
==
HA_EXTRA_KEYREAD
)
return
0
;
return
mi_extra
(
file
,
operation
,
0
);
DBUG_RETURN
(
0
)
;
DBUG_RETURN
(
mi_extra
(
file
,
operation
,
0
)
);
}
...
...
@@ -945,34 +1010,44 @@ int ha_myisam::extra(enum ha_extra_function operation)
int
ha_myisam
::
extra_opt
(
enum
ha_extra_function
operation
,
ulong
cache_size
)
{
DBUG_ENTER
(
"ha_myisam::extra_opt"
);
if
((
specialflag
&
SPECIAL_SAFE_MODE
)
&
(
operation
==
HA_EXTRA_WRITE_CACHE
||
operation
==
HA_EXTRA_BULK_INSERT_BEGIN
))
return
0
;
return
mi_extra
(
file
,
operation
,
(
void
*
)
&
cache_size
);
DBUG_RETURN
(
0
)
;
DBUG_RETURN
(
mi_extra
(
file
,
operation
,
(
void
*
)
&
cache_size
)
);
}
int
ha_myisam
::
reset
(
void
)
{
return
mi_extra
(
file
,
HA_EXTRA_RESET
,
0
);
DBUG_ENTER
(
"ha_myisam::reset"
);
DBUG_RETURN
(
mi_extra
(
file
,
HA_EXTRA_RESET
,
0
));
}
int
ha_myisam
::
delete_all_rows
()
{
return
mi_delete_all_rows
(
file
);
DBUG_ENTER
(
"ha_myisam::delete_all_rows"
);
DBUG_RETURN
(
mi_delete_all_rows
(
file
));
}
int
ha_myisam
::
delete_table
(
const
char
*
name
)
{
return
mi_delete_table
(
name
);
DBUG_ENTER
(
"ha_myisam::delete_table"
);
DBUG_RETURN
(
mi_delete_table
(
name
));
}
int
ha_myisam
::
external_lock
(
THD
*
thd
,
int
lock_type
)
{
DBUG_ENTER
(
"ha_myisam::external_lock"
);
if
(
!
table
->
tmp_table
)
return
mi_lock_database
(
file
,
lock_type
);
return
0
;
DBUG_RETURN
(
mi_lock_database
(
file
,
lock_type
)
);
DBUG_RETURN
(
0
)
;
}
...
...
@@ -980,14 +1055,18 @@ THR_LOCK_DATA **ha_myisam::store_lock(THD *thd,
THR_LOCK_DATA
**
to
,
enum
thr_lock_type
lock_type
)
{
DBUG_ENTER
(
"**ha_myisam::store_lock"
);
if
(
lock_type
!=
TL_IGNORE
&&
file
->
lock
.
type
==
TL_UNLOCK
)
file
->
lock
.
type
=
lock_type
;
*
to
++=
&
file
->
lock
;
return
to
;
DBUG_RETURN
(
to
)
;
}
void
ha_myisam
::
update_create_info
(
HA_CREATE_INFO
*
create_info
)
{
DBUG_ENTER
(
"ha_myisam::update_create_info"
);
table
->
file
->
info
(
HA_STATUS_AUTO
|
HA_STATUS_CONST
);
if
(
!
(
create_info
->
used_fields
&
HA_CREATE_USED_AUTO
))
{
...
...
@@ -1001,6 +1080,7 @@ void ha_myisam::update_create_info(HA_CREATE_INFO *create_info)
}
create_info
->
data_file_name
=
data_file_name
;
create_info
->
index_file_name
=
index_file_name
;
DBUG_VOID_RETURN
;
}
...
...
@@ -1196,16 +1276,20 @@ int ha_myisam::create(const char *name, register TABLE *table_arg,
int
ha_myisam
::
rename_table
(
const
char
*
from
,
const
char
*
to
)
{
return
mi_rename
(
from
,
to
);
DBUG_ENTER
(
"ha_myisam::rename_table"
);
DBUG_RETURN
(
mi_rename
(
from
,
to
));
}
longlong
ha_myisam
::
get_auto_increment
()
{
DBUG_ENTER
(
"ha_myisam::get_auto_increment"
);
if
(
!
table
->
next_number_key_offset
)
{
// Autoincrement at key-start
ha_myisam
::
info
(
HA_STATUS_AUTO
);
return
auto_increment_value
;
DBUG_RETURN
(
auto_increment_value
)
;
}
if
(
table
->
bulk_insert
)
...
...
@@ -1226,7 +1310,7 @@ longlong ha_myisam::get_auto_increment()
nr
=
(
longlong
)
table
->
next_number_field
->
val_int_offset
(
table
->
rec_buff_length
)
+
1
;
extra
(
HA_EXTRA_NO_KEYREAD
);
return
nr
;
DBUG_RETURN
(
nr
)
;
}
...
...
@@ -1236,25 +1320,28 @@ ha_rows ha_myisam::records_in_range(int inx,
const
byte
*
end_key
,
uint
end_key_len
,
enum
ha_rkey_function
end_search_flag
)
{
return
(
ha_rows
)
mi_records_in_range
(
file
,
DBUG_ENTER
(
"ha_myisam::records_in_range"
);
DBUG_RETURN
((
ha_rows
)
mi_records_in_range
(
file
,
inx
,
start_key
,
start_key_len
,
start_search_flag
,
end_key
,
end_key_len
,
end_search_flag
);
end_search_flag
)
)
;
}
int
ha_myisam
::
ft_read
(
byte
*
buf
)
{
int
error
;
DBUG_ENTER
(
"ha_myisam::ft_read"
);
if
(
!
ft_handler
)
return
-
1
;
DBUG_RETURN
(
-
1
)
;
thread_safe_increment
(
ha_read_next_count
,
&
LOCK_status
);
// why ?
error
=
ft_handler
->
please
->
read_next
(
ft_handler
,(
char
*
)
buf
);
table
->
status
=
error
?
STATUS_NOT_FOUND
:
0
;
return
error
;
DBUG_RETURN
(
error
)
;
}
sql/ha_myisammrg.cc
View file @
cd6bf73f
...
...
@@ -38,12 +38,14 @@ const char **ha_myisammrg::bas_ext() const
int
ha_myisammrg
::
open
(
const
char
*
name
,
int
mode
,
uint
test_if_locked
)
{
char
name_buff
[
FN_REFLEN
];
DBUG_ENTER
(
"ha_myisammrg::open"
);
DBUG_PRINT
(
"info"
,
(
"ha_myisammrg::open"
));
if
(
!
(
file
=
myrg_open
(
fn_format
(
name_buff
,
name
,
""
,
""
,
2
|
4
),
mode
,
test_if_locked
)))
{
DBUG_PRINT
(
"info"
,
(
"ha_myisammrg::open exit %d"
,
my_errno
));
return
(
my_errno
?
my_errno
:
-
1
);
DBUG_RETURN
((
my_errno
?
my_errno
:
-
1
)
);
}
DBUG_PRINT
(
"info"
,
(
"ha_myisammrg::open myrg_extrafunc..."
))
myrg_extrafunc
(
file
,
query_cache_invalidate_by_MyISAM_filename_ref
);
...
...
@@ -65,132 +67,165 @@ int ha_myisammrg::open(const char *name, int mode, uint test_if_locked)
if
(
table
->
crashed
)
goto
err
;
#endif
return
(
0
);
DBUG_RETURN
((
0
)
);
err:
myrg_close
(
file
);
file
=
0
;
return
(
my_errno
=
HA_ERR_WRONG_TABLE_DEF
);
DBUG_RETURN
((
my_errno
=
HA_ERR_WRONG_TABLE_DEF
)
);
}
int
ha_myisammrg
::
close
(
void
)
{
return
myrg_close
(
file
);
DBUG_ENTER
(
"ha_myisammrg::close"
);
DBUG_RETURN
(
myrg_close
(
file
));
}
int
ha_myisammrg
::
write_row
(
byte
*
buf
)
{
DBUG_ENTER
(
"ha_myisammrg::write_row"
);
statistic_increment
(
ha_write_count
,
&
LOCK_status
);
if
(
table
->
time_stamp
)
update_timestamp
(
buf
+
table
->
time_stamp
-
1
);
if
(
table
->
next_number_field
&&
buf
==
table
->
record
[
0
])
update_auto_increment
();
return
myrg_write
(
file
,
buf
);
DBUG_RETURN
(
myrg_write
(
file
,
buf
)
);
}
int
ha_myisammrg
::
update_row
(
const
byte
*
old_data
,
byte
*
new_data
)
{
DBUG_ENTER
(
"ha_myisammrg::update_row"
);
statistic_increment
(
ha_update_count
,
&
LOCK_status
);
if
(
table
->
time_stamp
)
update_timestamp
(
new_data
+
table
->
time_stamp
-
1
);
return
myrg_update
(
file
,
old_data
,
new_data
);
DBUG_RETURN
(
myrg_update
(
file
,
old_data
,
new_data
)
);
}
int
ha_myisammrg
::
delete_row
(
const
byte
*
buf
)
{
DBUG_ENTER
(
"ha_myisammrg::delete_row"
);
statistic_increment
(
ha_delete_count
,
&
LOCK_status
);
return
myrg_delete
(
file
,
buf
);
DBUG_RETURN
(
myrg_delete
(
file
,
buf
)
);
}
int
ha_myisammrg
::
index_read
(
byte
*
buf
,
const
byte
*
key
,
uint
key_len
,
enum
ha_rkey_function
find_flag
)
{
DBUG_ENTER
(
"ha_myisammrg::index_read"
);
statistic_increment
(
ha_read_key_count
,
&
LOCK_status
);
int
error
=
myrg_rkey
(
file
,
buf
,
active_index
,
key
,
key_len
,
find_flag
);
table
->
status
=
error
?
STATUS_NOT_FOUND
:
0
;
return
error
;
DBUG_RETURN
(
error
)
;
}
int
ha_myisammrg
::
index_read_idx
(
byte
*
buf
,
uint
index
,
const
byte
*
key
,
uint
key_len
,
enum
ha_rkey_function
find_flag
)
{
DBUG_ENTER
(
"ha_myisammrg::index_read_idx"
);
statistic_increment
(
ha_read_key_count
,
&
LOCK_status
);
int
error
=
myrg_rkey
(
file
,
buf
,
index
,
key
,
key_len
,
find_flag
);
table
->
status
=
error
?
STATUS_NOT_FOUND
:
0
;
return
error
;
DBUG_RETURN
(
error
)
;
}
int
ha_myisammrg
::
index_read_last
(
byte
*
buf
,
const
byte
*
key
,
uint
key_len
)
{
DBUG_ENTER
(
"ha_myisammrg::index_read_last"
);
statistic_increment
(
ha_read_key_count
,
&
LOCK_status
);
int
error
=
myrg_rkey
(
file
,
buf
,
active_index
,
key
,
key_len
,
HA_READ_PREFIX_LAST
);
table
->
status
=
error
?
STATUS_NOT_FOUND
:
0
;
return
error
;
DBUG_RETURN
(
error
)
;
}
int
ha_myisammrg
::
index_next
(
byte
*
buf
)
{
DBUG_ENTER
(
"ha_myisammrg::index_next"
);
statistic_increment
(
ha_read_next_count
,
&
LOCK_status
);
int
error
=
myrg_rnext
(
file
,
buf
,
active_index
);
table
->
status
=
error
?
STATUS_NOT_FOUND
:
0
;
return
error
;
DBUG_RETURN
(
error
)
;
}
int
ha_myisammrg
::
index_prev
(
byte
*
buf
)
{
DBUG_ENTER
(
"ha_myisammrg::index_prev"
);
statistic_increment
(
ha_read_prev_count
,
&
LOCK_status
);
int
error
=
myrg_rprev
(
file
,
buf
,
active_index
);
table
->
status
=
error
?
STATUS_NOT_FOUND
:
0
;
return
error
;
DBUG_RETURN
(
error
)
;
}
int
ha_myisammrg
::
index_first
(
byte
*
buf
)
{
DBUG_ENTER
(
"ha_myisammrg::index_first"
);
statistic_increment
(
ha_read_first_count
,
&
LOCK_status
);
int
error
=
myrg_rfirst
(
file
,
buf
,
active_index
);
table
->
status
=
error
?
STATUS_NOT_FOUND
:
0
;
return
error
;
DBUG_RETURN
(
error
)
;
}
int
ha_myisammrg
::
index_last
(
byte
*
buf
)
{
DBUG_ENTER
(
"ha_myisammrg::index_last"
);
statistic_increment
(
ha_read_last_count
,
&
LOCK_status
);
int
error
=
myrg_rlast
(
file
,
buf
,
active_index
);
table
->
status
=
error
?
STATUS_NOT_FOUND
:
0
;
return
error
;
DBUG_RETURN
(
error
)
;
}
int
ha_myisammrg
::
rnd_init
(
bool
scan
)
{
return
myrg_extra
(
file
,
HA_EXTRA_RESET
,
0
);
DBUG_ENTER
(
"ha_myisammrg::rnd_init"
);
DBUG_RETURN
(
myrg_extra
(
file
,
HA_EXTRA_RESET
,
0
));
}
int
ha_myisammrg
::
rnd_next
(
byte
*
buf
)
{
DBUG_ENTER
(
"ha_myisammrg::rnd_next"
);
statistic_increment
(
ha_read_rnd_next_count
,
&
LOCK_status
);
int
error
=
myrg_rrnd
(
file
,
buf
,
HA_OFFSET_ERROR
);
table
->
status
=
error
?
STATUS_NOT_FOUND
:
0
;
return
error
;
DBUG_RETURN
(
error
)
;
}
int
ha_myisammrg
::
rnd_pos
(
byte
*
buf
,
byte
*
pos
)
{
DBUG_ENTER
(
"ha_myisammrg::rnd_pos"
);
statistic_increment
(
ha_read_rnd_count
,
&
LOCK_status
);
int
error
=
myrg_rrnd
(
file
,
buf
,
ha_get_ptr
(
pos
,
ref_length
));
table
->
status
=
error
?
STATUS_NOT_FOUND
:
0
;
return
error
;
DBUG_RETURN
(
error
)
;
}
void
ha_myisammrg
::
position
(
const
byte
*
record
)
{
ulonglong
position
=
myrg_position
(
file
);
DBUG_ENTER
(
"ha_myisammrg::position"
);
ha_store_ptr
(
ref
,
ref_length
,
(
my_off_t
)
position
);
DBUG_VOID_RETURN
;
}
void
ha_myisammrg
::
info
(
uint
flag
)
{
MYMERGE_INFO
info
;
DBUG_ENTER
(
"ha_myisammrg::info"
);
(
void
)
myrg_status
(
file
,
&
info
,
flag
);
/*
The following fails if one has not compiled MySQL with -DBIG_TABLES
...
...
@@ -216,17 +251,20 @@ void ha_myisammrg::info(uint flag)
#else
ref_length
=
4
;
// Can't be > than my_off_t
#endif
DBUG_VOID_RETURN
;
}
int
ha_myisammrg
::
extra
(
enum
ha_extra_function
operation
)
{
DBUG_ENTER
(
"ha_myisammrg::extra"
);
/* As this is just a mapping, we don't have to force the underlying
tables to be closed */
if
(
operation
==
HA_EXTRA_FORCE_REOPEN
||
operation
==
HA_EXTRA_PREPARE_FOR_DELETE
)
return
0
;
return
myrg_extra
(
file
,
operation
,
0
);
DBUG_RETURN
(
0
)
;
DBUG_RETURN
(
myrg_extra
(
file
,
operation
,
0
)
);
}
...
...
@@ -234,27 +272,35 @@ int ha_myisammrg::extra(enum ha_extra_function operation)
int
ha_myisammrg
::
extra_opt
(
enum
ha_extra_function
operation
,
ulong
cache_size
)
{
DBUG_ENTER
(
"ha_myisammrg::extra_opt"
);
if
((
specialflag
&
SPECIAL_SAFE_MODE
)
&
(
operation
==
HA_EXTRA_WRITE_CACHE
||
operation
==
HA_EXTRA_BULK_INSERT_BEGIN
))
return
0
;
return
myrg_extra
(
file
,
operation
,
(
void
*
)
&
cache_size
);
DBUG_RETURN
(
0
)
;
DBUG_RETURN
(
myrg_extra
(
file
,
operation
,
(
void
*
)
&
cache_size
)
);
}
int
ha_myisammrg
::
reset
(
void
)
{
return
myrg_extra
(
file
,
HA_EXTRA_RESET
,
0
);
DBUG_ENTER
(
"ha_myisammrg::reset"
);
DBUG_RETURN
(
myrg_extra
(
file
,
HA_EXTRA_RESET
,
0
));
}
int
ha_myisammrg
::
external_lock
(
THD
*
thd
,
int
lock_type
)
{
return
myrg_lock_database
(
file
,
lock_type
);
DBUG_ENTER
(
"ha_myisammrg::external_lock"
);
DBUG_RETURN
(
myrg_lock_database
(
file
,
lock_type
));
}
uint
ha_myisammrg
::
lock_count
(
void
)
const
{
return
file
->
tables
;
DBUG_ENTER
(
"ha_myisammrg::lock_count"
);
DBUG_RETURN
(
file
->
tables
);
}
...
...
@@ -263,6 +309,7 @@ THR_LOCK_DATA **ha_myisammrg::store_lock(THD *thd,
enum
thr_lock_type
lock_type
)
{
MYRG_TABLE
*
open_table
;
DBUG_ENTER
(
"**ha_myisammrg::store_lock"
);
for
(
open_table
=
file
->
open_tables
;
open_table
!=
file
->
end_table
;
...
...
@@ -272,13 +319,14 @@ THR_LOCK_DATA **ha_myisammrg::store_lock(THD *thd,
if
(
lock_type
!=
TL_IGNORE
&&
open_table
->
table
->
lock
.
type
==
TL_UNLOCK
)
open_table
->
table
->
lock
.
type
=
lock_type
;
}
return
to
;
DBUG_RETURN
(
to
)
;
}
void
ha_myisammrg
::
update_create_info
(
HA_CREATE_INFO
*
create_info
)
{
// [phi] auto_increment stuff is missing (but currently not needed)
DBUG_ENTER
(
"ha_myisammrg::update_create_info"
);
// [phi] auto_increment stuff is missing (but currently not needed)
if
(
!
(
create_info
->
used_fields
&
HA_CREATE_USED_UNION
))
{
MYRG_TABLE
*
open_table
;
...
...
@@ -327,7 +375,28 @@ int ha_myisammrg::create(const char *name, register TABLE *form,
sizeof
(
char
*
))))
DBUG_RETURN
(
1
);
for
(
pos
=
table_names
;
tables
;
tables
=
tables
->
next
)
*
pos
++=
tables
->
real_name
;
{
char
*
table_name
;
if
(
create_info
->
options
&
HA_LEX_CREATE_TMP_TABLE
)
{
TABLE
**
tbl
=
find_temporary_table
(
current_thd
,
tables
->
db
,
tables
->
real_name
);
if
(
!
tbl
)
{
table_name
=
sql_alloc
(
1
+
my_snprintf
(
buff
,
FN_REFLEN
,
"%s/%s/%s"
,
mysql_real_data_home
,
tables
->
db
,
tables
->
real_name
));
if
(
!
table_name
)
DBUG_RETURN
(
1
);
strcpy
(
table_name
,
buff
);
}
else
table_name
=
(
*
tbl
)
->
path
;
}
else
table_name
=
tables
->
real_name
;
*
pos
++=
table_name
;
}
*
pos
=
0
;
DBUG_RETURN
(
myrg_create
(
fn_format
(
buff
,
name
,
""
,
""
,
2
+
4
+
16
),
(
const
char
**
)
table_names
,
...
...
@@ -338,6 +407,8 @@ int ha_myisammrg::create(const char *name, register TABLE *form,
void
ha_myisammrg
::
append_create_info
(
String
*
packet
)
{
char
buff
[
FN_REFLEN
];
DBUG_ENTER
(
"ha_myisammrg::append_create_info"
);
if
(
file
->
merge_insert_method
!=
MERGE_INSERT_DISABLED
)
{
packet
->
append
(
" INSERT_METHOD="
,
15
);
...
...
@@ -357,4 +428,5 @@ void ha_myisammrg::append_create_info(String *packet)
packet
->
append
(
buff
,(
uint
)
strlen
(
buff
));
}
packet
->
append
(
')'
);
DBUG_VOID_RETURN
;
}
sql/handler.cc
View file @
cd6bf73f
...
...
@@ -72,14 +72,16 @@ TYPELIB tx_isolation_typelib= {array_elements(tx_isolation_names)-1,"",
enum
db_type
ha_checktype
(
enum
db_type
database_type
)
{
DBUG_ENTER
(
"ha_checktype"
);
switch
(
database_type
)
{
#ifdef HAVE_BERKELEY_DB
case
DB_TYPE_BERKELEY_DB
:
return
(
berkeley_skip
?
DB_TYPE_MYISAM
:
database_type
);
DBUG_RETURN
((
berkeley_skip
?
DB_TYPE_MYISAM
:
database_type
)
);
#endif
#ifdef HAVE_INNOBASE_DB
case
DB_TYPE_INNODB
:
return
(
innodb_skip
?
DB_TYPE_MYISAM
:
database_type
);
DBUG_RETURN
((
innodb_skip
?
DB_TYPE_MYISAM
:
database_type
)
);
#endif
#ifndef NO_HASH
case
DB_TYPE_HASH
:
...
...
@@ -91,52 +93,57 @@ enum db_type ha_checktype(enum db_type database_type)
case
DB_TYPE_HEAP
:
case
DB_TYPE_MYISAM
:
case
DB_TYPE_MRG_MYISAM
:
return
(
database_type
);
/* Database exists on system */
DBUG_RETURN
((
database_type
)
);
/* Database exists on system */
default:
break
;
}
return
(
DB_TYPE_MYISAM
);
/* Use this as default */
DBUG_RETURN
((
DB_TYPE_MYISAM
)
);
/* Use this as default */
}
/* ha_checktype */
handler
*
get_new_handler
(
TABLE
*
table
,
enum
db_type
db_type
)
{
DBUG_ENTER
(
"*get_new_handler"
);
switch
(
db_type
)
{
#ifndef NO_HASH
return
new
ha_hash
(
table
);
DBUG_RETURN
(
new
ha_hash
(
table
)
);
#endif
#ifdef HAVE_ISAM
case
DB_TYPE_MRG_ISAM
:
return
new
ha_isammrg
(
table
);
DBUG_RETURN
(
new
ha_isammrg
(
table
)
);
case
DB_TYPE_ISAM
:
return
new
ha_isam
(
table
);
DBUG_RETURN
(
new
ha_isam
(
table
)
);
#endif
#ifdef HAVE_BERKELEY_DB
case
DB_TYPE_BERKELEY_DB
:
return
new
ha_berkeley
(
table
);
DBUG_RETURN
(
new
ha_berkeley
(
table
)
);
#endif
#ifdef HAVE_INNOBASE_DB
case
DB_TYPE_INNODB
:
return
new
ha_innobase
(
table
);
DBUG_RETURN
(
new
ha_innobase
(
table
)
);
#endif
case
DB_TYPE_HEAP
:
return
new
ha_heap
(
table
);
DBUG_RETURN
(
new
ha_heap
(
table
)
);
case
DB_TYPE_MYISAM
:
default:
// should never happen
return
new
ha_myisam
(
table
);
DBUG_RETURN
(
new
ha_myisam
(
table
)
);
case
DB_TYPE_MRG_MYISAM
:
return
new
ha_myisammrg
(
table
);
DBUG_RETURN
(
new
ha_myisammrg
(
table
)
);
}
DBUG_RETURN
(
NULL
);
// impossible
}
int
ha_init
()
{
DBUG_ENTER
(
"ha_init"
);
#ifdef HAVE_BERKELEY_DB
if
(
!
berkeley_skip
)
{
int
error
;
if
((
error
=
berkeley_init
()))
return
error
;
DBUG_RETURN
(
error
)
;
if
(
!
berkeley_skip
)
// If we couldn't use handler
opt_using_transactions
=
1
;
else
...
...
@@ -147,14 +154,14 @@ int ha_init()
if
(
!
innodb_skip
)
{
if
(
innobase_init
())
return
-
1
;
DBUG_RETURN
(
-
1
)
;
if
(
!
innodb_skip
)
// If we couldn't use handler
opt_using_transactions
=
1
;
else
have_innodb
=
SHOW_OPTION_DISABLED
;
}
#endif
return
0
;
DBUG_RETURN
(
0
)
;
}
/* close, flush or restart databases */
...
...
@@ -163,6 +170,8 @@ int ha_init()
int
ha_panic
(
enum
ha_panic_function
flag
)
{
int
error
=
0
;
DBUG_ENTER
(
"ha_panic"
);
#ifndef NO_HASH
error
|=
h_panic
(
flag
);
/* fix hash */
#endif
...
...
@@ -181,23 +190,29 @@ int ha_panic(enum ha_panic_function flag)
if
(
!
innodb_skip
)
error
|=
innobase_end
();
#endif
return
error
;
DBUG_RETURN
(
error
)
;
}
/* ha_panic */
void
ha_drop_database
(
char
*
path
)
{
DBUG_ENTER
(
"ha_drop_database"
);
#ifdef HAVE_INNOBASE_DB
if
(
!
innodb_skip
)
innobase_drop_database
(
path
);
#endif
DBUG_VOID_RETURN
;
}
void
ha_close_connection
(
THD
*
thd
)
{
DBUG_ENTER
(
"ha_close_connection"
);
#ifdef HAVE_INNOBASE_DB
if
(
!
innodb_skip
)
innobase_close_connection
(
thd
);
#endif
DBUG_VOID_RETURN
;
}
/*
...
...
@@ -247,6 +262,8 @@ int ha_report_binlog_offset_and_commit(THD *thd,
my_off_t
end_offset
)
{
int
error
=
0
;
DBUG_ENTER
(
"ha_report_binlog_offset_and_commit"
);
#ifdef HAVE_INNOBASE_DB
THD_TRANS
*
trans
;
trans
=
&
thd
->
transaction
.
all
;
...
...
@@ -263,7 +280,7 @@ int ha_report_binlog_offset_and_commit(THD *thd,
trans
->
innodb_active_trans
=
0
;
}
#endif
return
error
;
DBUG_RETURN
(
error
)
;
}
int
ha_commit_trans
(
THD
*
thd
,
THD_TRANS
*
trans
)
...
...
@@ -381,6 +398,8 @@ int ha_rollback_trans(THD *thd, THD_TRANS *trans)
bool
ha_flush_logs
()
{
bool
result
=
0
;
DBUG_ENTER
(
"ha_flush_logs"
);
#ifdef HAVE_BERKELEY_DB
if
(
!
berkeley_skip
&&
berkeley_flush_logs
())
result
=
1
;
...
...
@@ -389,7 +408,7 @@ bool ha_flush_logs()
if
(
!
innodb_skip
&&
innobase_flush_logs
())
result
=
1
;
#endif
return
result
;
DBUG_RETURN
(
result
)
;
}
/*
...
...
@@ -400,15 +419,19 @@ bool ha_flush_logs()
int
ha_delete_table
(
enum
db_type
table_type
,
const
char
*
path
)
{
handler
*
file
=
get_new_handler
((
TABLE
*
)
0
,
table_type
);
DBUG_ENTER
(
"ha_delete_table"
);
if
(
!
file
)
return
ENOENT
;
DBUG_RETURN
(
ENOENT
)
;
int
error
=
file
->
delete_table
(
path
);
delete
file
;
return
error
;
DBUG_RETURN
(
error
)
;
}
void
ha_store_ptr
(
byte
*
buff
,
uint
pack_length
,
my_off_t
pos
)
{
DBUG_ENTER
(
"ha_store_ptr"
);
switch
(
pack_length
)
{
#if SIZEOF_OFF_T > 4
case
8
:
mi_int8store
(
buff
,
pos
);
break
;
...
...
@@ -421,12 +444,14 @@ void ha_store_ptr(byte *buff, uint pack_length, my_off_t pos)
case
2
:
mi_int2store
(
buff
,(
uint
)
pos
);
break
;
case
1
:
buff
[
0
]
=
(
uchar
)
pos
;
break
;
}
return
;
DBUG_VOID_RETURN
;
}
my_off_t
ha_get_ptr
(
byte
*
ptr
,
uint
pack_length
)
{
my_off_t
pos
;
DBUG_ENTER
(
"ha_get_ptr"
);
switch
(
pack_length
)
{
#if SIZEOF_OFF_T > 4
case
8
:
...
...
@@ -458,7 +483,7 @@ my_off_t ha_get_ptr(byte *ptr, uint pack_length)
pos
=
0
;
// Impossible
break
;
}
return
pos
;
DBUG_RETURN
(
pos
)
;
}
/****************************************************************************
...
...
@@ -512,32 +537,44 @@ int handler::ha_open(const char *name, int mode, int test_if_locked)
int
handler
::
check
(
THD
*
thd
,
HA_CHECK_OPT
*
check_opt
)
{
return
HA_ADMIN_NOT_IMPLEMENTED
;
DBUG_ENTER
(
"handler::check"
);
DBUG_RETURN
(
HA_ADMIN_NOT_IMPLEMENTED
);
}
int
handler
::
backup
(
THD
*
thd
,
HA_CHECK_OPT
*
check_opt
)
{
return
HA_ADMIN_NOT_IMPLEMENTED
;
DBUG_ENTER
(
"handler::backup"
);
DBUG_RETURN
(
HA_ADMIN_NOT_IMPLEMENTED
);
}
int
handler
::
restore
(
THD
*
thd
,
HA_CHECK_OPT
*
check_opt
)
{
return
HA_ADMIN_NOT_IMPLEMENTED
;
DBUG_ENTER
(
"handler::restore"
);
DBUG_RETURN
(
HA_ADMIN_NOT_IMPLEMENTED
);
}
int
handler
::
repair
(
THD
*
thd
,
HA_CHECK_OPT
*
check_opt
)
{
return
HA_ADMIN_NOT_IMPLEMENTED
;
DBUG_ENTER
(
"handler::repair"
);
DBUG_RETURN
(
HA_ADMIN_NOT_IMPLEMENTED
);
}
int
handler
::
optimize
(
THD
*
thd
,
HA_CHECK_OPT
*
check_opt
)
{
return
HA_ADMIN_NOT_IMPLEMENTED
;
DBUG_ENTER
(
"handler::optimize"
);
DBUG_RETURN
(
HA_ADMIN_NOT_IMPLEMENTED
);
}
int
handler
::
analyze
(
THD
*
thd
,
HA_CHECK_OPT
*
check_opt
)
{
return
HA_ADMIN_NOT_IMPLEMENTED
;
DBUG_ENTER
(
"handler::analyze"
);
DBUG_RETURN
(
HA_ADMIN_NOT_IMPLEMENTED
);
}
/*
...
...
@@ -582,7 +619,9 @@ int handler::read_first_row(byte * buf, uint primary_key)
int
handler
::
restart_rnd_next
(
byte
*
buf
,
byte
*
pos
)
{
return
HA_ERR_WRONG_COMMAND
;
DBUG_ENTER
(
"handler::restart_rnd_next"
);
DBUG_RETURN
(
HA_ERR_WRONG_COMMAND
);
}
...
...
@@ -591,6 +630,8 @@ int handler::restart_rnd_next(byte *buf, byte *pos)
void
handler
::
update_timestamp
(
byte
*
record
)
{
long
skr
=
(
long
)
current_thd
->
query_start
();
DBUG_ENTER
(
"handler::update_timestamp"
);
#ifdef WORDS_BIGENDIAN
if
(
table
->
db_low_byte_first
)
{
...
...
@@ -599,7 +640,7 @@ void handler::update_timestamp(byte *record)
else
#endif
longstore
(
record
,
skr
);
return
;
DBUG_VOID_RETURN
;
}
/*
...
...
@@ -633,6 +674,7 @@ longlong handler::get_auto_increment()
{
longlong
nr
;
int
error
;
DBUG_ENTER
(
"handler::get_auto_increment"
);
(
void
)
extra
(
HA_EXTRA_KEYREAD
);
index_init
(
table
->
next_number_index
);
...
...
@@ -656,7 +698,7 @@ longlong handler::get_auto_increment()
val_int_offset
(
table
->
rec_buff_length
)
+
1
;
index_end
();
(
void
)
extra
(
HA_EXTRA_NO_KEYREAD
);
return
nr
;
DBUG_RETURN
(
nr
)
;
}
/* Print error that we got from handler function */
...
...
@@ -778,6 +820,8 @@ uint handler::get_dup_key(int error)
int
handler
::
delete_table
(
const
char
*
name
)
{
int
error
=
0
;
DBUG_ENTER
(
"handler::delete_table"
);
for
(
const
char
**
ext
=
bas_ext
();
*
ext
;
ext
++
)
{
if
(
delete_file
(
name
,
*
ext
,
2
))
...
...
@@ -786,7 +830,7 @@ int handler::delete_table(const char *name)
break
;
}
}
return
error
;
DBUG_RETURN
(
error
)
;
}
...
...
@@ -807,14 +851,16 @@ int handler::rename_table(const char * from, const char * to)
int
ha_recovery_logging
(
THD
*
thd
,
bool
on
)
{
int
error
=
0
;
DBUG_ENTER
(
"ha_recovery_logging"
);
DBUG_RETURN
(
error
);
}
int
handler
::
index_next_same
(
byte
*
buf
,
const
byte
*
key
,
uint
keylen
)
{
int
error
;
DBUG_ENTER
(
"handler::index_next_same"
);
if
(
!
(
error
=
index_next
(
buf
)))
{
if
(
key_cmp
(
table
,
key
,
active_index
,
keylen
))
...
...
@@ -823,7 +869,7 @@ int handler::index_next_same(byte *buf, const byte *key, uint keylen)
error
=
HA_ERR_END_OF_FILE
;
}
}
return
error
;
DBUG_RETURN
(
error
)
;
}
...
...
@@ -836,7 +882,9 @@ int handler::index_next_same(byte *buf, const byte *key, uint keylen)
int
handler
::
delete_all_rows
()
{
return
(
my_errno
=
HA_ERR_WRONG_COMMAND
);
DBUG_ENTER
(
"handler::delete_all_rows"
);
DBUG_RETURN
((
my_errno
=
HA_ERR_WRONG_COMMAND
));
}
/****************************************************************************
...
...
@@ -882,26 +930,37 @@ int ha_create_table(const char *name, HA_CREATE_INFO *create_info,
void
ha_key_cache
(
void
)
{
DBUG_ENTER
(
"ha_key_cache"
);
if
(
keybuff_size
)
(
void
)
init_key_cache
(
keybuff_size
);
DBUG_VOID_RETURN
;
}
void
ha_resize_key_cache
(
void
)
{
DBUG_ENTER
(
"ha_resize_key_cache"
);
(
void
)
resize_key_cache
(
keybuff_size
);
DBUG_VOID_RETURN
;
}
static
int
NEAR_F
delete_file
(
const
char
*
name
,
const
char
*
ext
,
int
extflag
)
{
char
buff
[
FN_REFLEN
];
DBUG_ENTER
(
"delete_file"
);
VOID
(
fn_format
(
buff
,
name
,
""
,
ext
,
extflag
|
4
));
return
(
my_delete_with_symlink
(
buff
,
MYF
(
MY_WME
)));
DBUG_RETURN
((
my_delete_with_symlink
(
buff
,
MYF
(
MY_WME
)
)));
}
void
st_ha_check_opt
::
init
()
{
DBUG_ENTER
(
"st_ha_check_opt::init"
);
flags
=
sql_flags
=
0
;
sort_buffer_size
=
current_thd
->
variables
.
myisam_sort_buff_size
;
DBUG_VOID_RETURN
;
}
sql/item_cmpfunc.cc
View file @
cd6bf73f
...
...
@@ -350,13 +350,19 @@ void Item_func_between::fix_length_and_dec()
*/
if
(
!
args
[
0
]
||
!
args
[
1
]
||
!
args
[
2
])
return
;
cmp_type
=
args
[
0
]
->
result_type
();
if
(
args
[
0
]
->
binary
)
cmp_type
=
item_cmp_type
(
args
[
0
]
->
result_type
(),
item_cmp_type
(
args
[
1
]
->
result_type
(),
args
[
2
]
->
result_type
()));
if
(
args
[
0
]
->
binary
|
args
[
1
]
->
binary
|
args
[
2
]
->
binary
)
string_compare
=
stringcmp
;
else
string_compare
=
sortcmp
;
// Make a special case of compare with fields to get nicer DATE comparisons
/*
Make a special case of compare with date/time and longlong fields.
They are compared as integers, so for const item this time-consuming
conversion can be done only once, not for every single comparison
*/
if
(
args
[
0
]
->
type
()
==
FIELD_ITEM
)
{
Field
*
field
=
((
Item_field
*
)
args
[
0
])
->
field
;
...
...
sql/mysqld.cc
View file @
cd6bf73f
...
...
@@ -1404,7 +1404,11 @@ information that should help you find out what is causing the crash.\n");
#endif
/* HAVE_STACKTRACE */
if
(
test_flags
&
TEST_CORE_ON_SIGNAL
)
{
fprintf
(
stderr
,
"Writing a core file
\n
"
);
fflush
(
stderr
);
write_core
(
sig
);
}
exit
(
1
);
}
...
...
sql/opt_range.cc
View file @
cd6bf73f
...
...
@@ -100,6 +100,8 @@ public:
{
// Get overlapping range
char
*
new_min
,
*
new_max
;
uint8
flag_min
,
flag_max
;
DBUG_ENTER
(
"*clone_and"
);
if
(
cmp_min_to_min
(
arg
)
>=
0
)
{
new_min
=
min_value
;
flag_min
=
min_flag
;
...
...
@@ -116,64 +118,83 @@ public:
{
new_max
=
arg
->
max_value
;
flag_max
=
arg
->
max_flag
;
}
return
new
SEL_ARG
(
field
,
part
,
new_min
,
new_max
,
flag_min
,
flag_max
,
test
(
maybe_flag
&&
arg
->
maybe_flag
));
DBUG_RETURN
(
new
SEL_ARG
(
field
,
part
,
new_min
,
new_max
,
flag_min
,
flag_max
,
test
(
maybe_flag
&&
arg
->
maybe_flag
))
)
;
}
SEL_ARG
*
clone_first
(
SEL_ARG
*
arg
)
{
// min <= X < arg->min
return
new
SEL_ARG
(
field
,
part
,
min_value
,
arg
->
min_value
,
DBUG_ENTER
(
"*clone_first"
);
DBUG_RETURN
(
new
SEL_ARG
(
field
,
part
,
min_value
,
arg
->
min_value
,
min_flag
,
arg
->
min_flag
&
NEAR_MIN
?
0
:
NEAR_MAX
,
maybe_flag
|
arg
->
maybe_flag
);
maybe_flag
|
arg
->
maybe_flag
)
)
;
}
SEL_ARG
*
clone_last
(
SEL_ARG
*
arg
)
{
// min <= X <= key_max
return
new
SEL_ARG
(
field
,
part
,
min_value
,
arg
->
max_value
,
min_flag
,
arg
->
max_flag
,
maybe_flag
|
arg
->
maybe_flag
);
DBUG_ENTER
(
"*clone_last"
);
DBUG_RETURN
(
new
SEL_ARG
(
field
,
part
,
min_value
,
arg
->
max_value
,
min_flag
,
arg
->
max_flag
,
maybe_flag
|
arg
->
maybe_flag
));
}
SEL_ARG
*
clone
(
SEL_ARG
*
new_parent
,
SEL_ARG
**
next
);
bool
copy_min
(
SEL_ARG
*
arg
)
{
// Get overlapping range
DBUG_ENTER
(
"copy_min"
);
if
(
cmp_min_to_min
(
arg
)
>
0
)
{
min_value
=
arg
->
min_value
;
min_flag
=
arg
->
min_flag
;
if
((
max_flag
&
(
NO_MAX_RANGE
|
NO_MIN_RANGE
))
==
(
NO_MAX_RANGE
|
NO_MIN_RANGE
))
return
1
;
// Full range
DBUG_RETURN
(
1
)
;
// Full range
}
maybe_flag
|=
arg
->
maybe_flag
;
return
0
;
DBUG_RETURN
(
0
)
;
}
bool
copy_max
(
SEL_ARG
*
arg
)
{
// Get overlapping range
DBUG_ENTER
(
"copy_max"
);
if
(
cmp_max_to_max
(
arg
)
<=
0
)
{
max_value
=
arg
->
max_value
;
max_flag
=
arg
->
max_flag
;
if
((
max_flag
&
(
NO_MAX_RANGE
|
NO_MIN_RANGE
))
==
(
NO_MAX_RANGE
|
NO_MIN_RANGE
))
return
1
;
// Full range
DBUG_RETURN
(
1
)
;
// Full range
}
maybe_flag
|=
arg
->
maybe_flag
;
return
0
;
DBUG_RETURN
(
0
)
;
}
void
copy_min_to_min
(
SEL_ARG
*
arg
)
{
DBUG_ENTER
(
"copy_min_to_min"
);
min_value
=
arg
->
min_value
;
min_flag
=
arg
->
min_flag
;
DBUG_VOID_RETURN
;
}
void
copy_min_to_max
(
SEL_ARG
*
arg
)
{
DBUG_ENTER
(
"copy_min_to_max"
);
max_value
=
arg
->
min_value
;
max_flag
=
arg
->
min_flag
&
NEAR_MIN
?
0
:
NEAR_MAX
;
DBUG_VOID_RETURN
;
}
void
copy_max_to_min
(
SEL_ARG
*
arg
)
{
DBUG_ENTER
(
"copy_max_to_min"
);
min_value
=
arg
->
max_value
;
min_flag
=
arg
->
max_flag
&
NEAR_MAX
?
0
:
NEAR_MIN
;
DBUG_VOID_RETURN
;
}
void
store
(
uint
length
,
char
**
min_key
,
uint
min_key_flag
,
char
**
max_key
,
uint
max_key_flag
)
{
DBUG_ENTER
(
"store"
);
if
(
!
(
min_flag
&
NO_MIN_RANGE
)
&&
!
(
min_key_flag
&
(
NO_MIN_RANGE
|
NEAR_MIN
)))
{
...
...
@@ -198,11 +219,14 @@ public:
memcpy
(
*
max_key
,
max_value
,
length
+
(
int
)
maybe_null
);
(
*
max_key
)
+=
length
+
(
int
)
maybe_null
;
}
DBUG_VOID_RETURN
;
}
void
store_min_key
(
KEY_PART
*
key
,
char
**
range_key
,
uint
*
range_key_flag
)
{
SEL_ARG
*
key_tree
=
first
();
DBUG_ENTER
(
"store_min_key"
);
key_tree
->
store
(
key
[
key_tree
->
part
].
part_length
,
range_key
,
*
range_key_flag
,
range_key
,
NO_MAX_RANGE
);
*
range_key_flag
|=
key_tree
->
min_flag
;
...
...
@@ -211,11 +235,14 @@ public:
!
(
*
range_key_flag
&
(
NO_MIN_RANGE
|
NEAR_MIN
))
&&
key_tree
->
next_key_part
->
type
==
SEL_ARG
::
KEY_RANGE
)
key_tree
->
next_key_part
->
store_min_key
(
key
,
range_key
,
range_key_flag
);
DBUG_VOID_RETURN
;
}
void
store_max_key
(
KEY_PART
*
key
,
char
**
range_key
,
uint
*
range_key_flag
)
{
SEL_ARG
*
key_tree
=
last
();
DBUG_ENTER
(
"store_max_key"
);
key_tree
->
store
(
key
[
key_tree
->
part
].
part_length
,
range_key
,
NO_MIN_RANGE
,
range_key
,
*
range_key_flag
);
(
*
range_key_flag
)
|=
key_tree
->
max_flag
;
...
...
@@ -224,6 +251,7 @@ public:
!
(
*
range_key_flag
&
(
NO_MAX_RANGE
|
NEAR_MAX
))
&&
key_tree
->
next_key_part
->
type
==
SEL_ARG
::
KEY_RANGE
)
key_tree
->
next_key_part
->
store_max_key
(
key
,
range_key
,
range_key_flag
);
DBUG_VOID_RETURN
;
}
SEL_ARG
*
insert
(
SEL_ARG
*
key
);
...
...
@@ -244,6 +272,8 @@ public:
}
void
increment_use_count
(
long
count
)
{
DBUG_ENTER
(
"increment_use_count"
);
if
(
next_key_part
)
{
next_key_part
->
use_count
+=
count
;
...
...
@@ -252,15 +282,19 @@ public:
if
(
pos
->
next_key_part
)
pos
->
increment_use_count
(
count
);
}
DBUG_VOID_RETURN
;
}
void
free_tree
()
{
DBUG_ENTER
(
"free_tree"
);
for
(
SEL_ARG
*
pos
=
first
();
pos
;
pos
=
pos
->
next
)
if
(
pos
->
next_key_part
)
{
pos
->
next_key_part
->
use_count
--
;
pos
->
next_key_part
->
free_tree
();
}
DBUG_VOID_RETURN
;
}
inline
SEL_ARG
**
parent_ptr
()
...
...
@@ -369,17 +403,23 @@ SQL_SELECT *make_select(TABLE *head, table_map const_tables,
SQL_SELECT
::
SQL_SELECT
()
:
quick
(
0
),
cond
(
0
),
free_cond
(
0
)
{
DBUG_ENTER
(
"SQL_SELECT::SQL_SELECT"
);
quick_keys
=
0
;
needed_reg
=
0
;
my_b_clear
(
&
file
);
DBUG_VOID_RETURN
;
}
SQL_SELECT
::~
SQL_SELECT
()
{
delete
quick
;
DBUG_ENTER
(
"SQL_SELECT::~SQL_SELECT"
);
if
(
free_cond
)
delete
cond
;
close_cached_file
(
&
file
);
DBUG_VOID_RETURN
;
}
#undef index // Fix for Unixware 7
...
...
@@ -388,6 +428,8 @@ QUICK_SELECT::QUICK_SELECT(TABLE *table,uint key_nr,bool no_alloc)
:
dont_free
(
0
),
error
(
0
),
index
(
key_nr
),
max_used_key_length
(
0
),
head
(
table
),
it
(
ranges
),
range
(
0
)
{
DBUG_ENTER
(
"QUICK_SELECT::QUICK_SELECT"
);
if
(
!
no_alloc
)
{
init_sql_alloc
(
&
alloc
,
1024
,
0
);
// Allocates everything here
...
...
@@ -398,15 +440,19 @@ QUICK_SELECT::QUICK_SELECT(TABLE *table,uint key_nr,bool no_alloc)
file
=
head
->
file
;
record
=
head
->
record
[
0
];
init
();
DBUG_VOID_RETURN
;
}
QUICK_SELECT
::~
QUICK_SELECT
()
{
DBUG_ENTER
(
"QUICK_SELECT::~QUICK_SELECT"
);
if
(
!
dont_free
)
{
file
->
index_end
();
free_root
(
&
alloc
,
MYF
(
0
));
}
DBUG_VOID_RETURN
;
}
QUICK_RANGE
::
QUICK_RANGE
()
...
...
@@ -416,6 +462,8 @@ QUICK_RANGE::QUICK_RANGE()
SEL_ARG
::
SEL_ARG
(
SEL_ARG
&
arg
)
:
Sql_alloc
()
{
DBUG_ENTER
(
"SEL_ARG::SEL_ARG"
);
type
=
arg
.
type
;
min_flag
=
arg
.
min_flag
;
max_flag
=
arg
.
max_flag
;
...
...
@@ -427,6 +475,7 @@ SEL_ARG::SEL_ARG(SEL_ARG &arg) :Sql_alloc()
max_value
=
arg
.
max_value
;
next_key_part
=
arg
.
next_key_part
;
use_count
=
1
;
elements
=
1
;
DBUG_VOID_RETURN
;
}
...
...
@@ -444,7 +493,10 @@ SEL_ARG::SEL_ARG(Field *f,const char *min_value_arg,const char *max_value_arg)
max_value
((
char
*
)
max_value_arg
),
next
(
0
),
prev
(
0
),
next_key_part
(
0
),
color
(
BLACK
),
type
(
KEY_RANGE
)
{
DBUG_ENTER
(
"SEL_ARG::SEL_ARG"
);
left
=
right
=
&
null_element
;
DBUG_VOID_RETURN
;
}
SEL_ARG
::
SEL_ARG
(
Field
*
field_
,
uint8
part_
,
char
*
min_value_
,
char
*
max_value_
,
...
...
@@ -454,12 +506,17 @@ SEL_ARG::SEL_ARG(Field *field_,uint8 part_,char *min_value_,char *max_value_,
field
(
field_
),
min_value
(
min_value_
),
max_value
(
max_value_
),
next
(
0
),
prev
(
0
),
next_key_part
(
0
),
color
(
BLACK
),
type
(
KEY_RANGE
)
{
DBUG_ENTER
(
"SEL_ARG::SEL_ARG"
);
left
=
right
=
&
null_element
;
DBUG_VOID_RETURN
;
}
SEL_ARG
*
SEL_ARG
::
clone
(
SEL_ARG
*
new_parent
,
SEL_ARG
**
next_arg
)
{
SEL_ARG
*
tmp
;
DBUG_ENTER
(
"*SEL_ARG::clone"
);
if
(
type
!=
KEY_RANGE
)
{
tmp
=
new
SEL_ARG
(
type
);
...
...
@@ -484,27 +541,31 @@ SEL_ARG *SEL_ARG::clone(SEL_ARG *new_parent,SEL_ARG **next_arg)
tmp
->
right
=
right
->
clone
(
tmp
,
next_arg
);
}
increment_use_count
(
1
);
return
tmp
;
DBUG_RETURN
(
tmp
)
;
}
SEL_ARG
*
SEL_ARG
::
first
()
{
SEL_ARG
*
next_arg
=
this
;
DBUG_ENTER
(
"*SEL_ARG::first"
);
if
(
!
next_arg
->
left
)
return
0
;
// MAYBE_KEY
DBUG_RETURN
(
0
)
;
// MAYBE_KEY
while
(
next_arg
->
left
!=
&
null_element
)
next_arg
=
next_arg
->
left
;
return
next_arg
;
DBUG_RETURN
(
next_arg
)
;
}
SEL_ARG
*
SEL_ARG
::
last
()
{
SEL_ARG
*
next_arg
=
this
;
DBUG_ENTER
(
"*SEL_ARG::last"
);
if
(
!
next_arg
->
right
)
return
0
;
// MAYBE_KEY
DBUG_RETURN
(
0
)
;
// MAYBE_KEY
while
(
next_arg
->
right
!=
&
null_element
)
next_arg
=
next_arg
->
right
;
return
next_arg
;
DBUG_RETURN
(
next_arg
)
;
}
/*
...
...
@@ -515,55 +576,59 @@ SEL_ARG *SEL_ARG::last()
static
int
sel_cmp
(
Field
*
field
,
char
*
a
,
char
*
b
,
uint8
a_flag
,
uint8
b_flag
)
{
int
cmp
;
DBUG_ENTER
(
"sel_cmp"
);
/* First check if there was a compare to a min or max element */
if
(
a_flag
&
(
NO_MIN_RANGE
|
NO_MAX_RANGE
))
{
if
((
a_flag
&
(
NO_MIN_RANGE
|
NO_MAX_RANGE
))
==
(
b_flag
&
(
NO_MIN_RANGE
|
NO_MAX_RANGE
)))
return
0
;
return
(
a_flag
&
NO_MIN_RANGE
)
?
-
1
:
1
;
DBUG_RETURN
(
0
)
;
DBUG_RETURN
((
a_flag
&
NO_MIN_RANGE
)
?
-
1
:
1
)
;
}
if
(
b_flag
&
(
NO_MIN_RANGE
|
NO_MAX_RANGE
))
return
(
b_flag
&
NO_MIN_RANGE
)
?
1
:
-
1
;
DBUG_RETURN
((
b_flag
&
NO_MIN_RANGE
)
?
1
:
-
1
)
;
if
(
field
->
real_maybe_null
())
// If null is part of key
{
if
(
*
a
!=
*
b
)
{
return
*
a
?
-
1
:
1
;
DBUG_RETURN
(
*
a
?
-
1
:
1
)
;
}
if
(
*
a
)
goto
end
;
// NULL where equal
a
++
;
b
++
;
// Skip NULL marker
}
cmp
=
field
->
key_cmp
((
byte
*
)
a
,(
byte
*
)
b
);
if
(
cmp
)
return
cmp
<
0
?
-
1
:
1
;
// The values differed
if
(
cmp
)
DBUG_RETURN
(
cmp
<
0
?
-
1
:
1
)
;
// The values differed
// Check if the compared equal arguments was defined with open/closed range
end:
if
(
a_flag
&
(
NEAR_MIN
|
NEAR_MAX
))
{
if
((
a_flag
&
(
NEAR_MIN
|
NEAR_MAX
))
==
(
b_flag
&
(
NEAR_MIN
|
NEAR_MAX
)))
return
0
;
DBUG_RETURN
(
0
)
;
if
(
!
(
b_flag
&
(
NEAR_MIN
|
NEAR_MAX
)))
return
(
a_flag
&
NEAR_MIN
)
?
2
:
-
2
;
return
(
a_flag
&
NEAR_MIN
)
?
1
:
-
1
;
DBUG_RETURN
((
a_flag
&
NEAR_MIN
)
?
2
:
-
2
)
;
DBUG_RETURN
((
a_flag
&
NEAR_MIN
)
?
1
:
-
1
)
;
}
if
(
b_flag
&
(
NEAR_MIN
|
NEAR_MAX
))
return
(
b_flag
&
NEAR_MIN
)
?
-
2
:
2
;
return
0
;
// The elements where equal
DBUG_RETURN
((
b_flag
&
NEAR_MIN
)
?
-
2
:
2
)
;
DBUG_RETURN
(
0
)
;
// The elements where equal
}
SEL_ARG
*
SEL_ARG
::
clone_tree
()
{
SEL_ARG
tmp_link
,
*
next_arg
,
*
root
;
DBUG_ENTER
(
"*SEL_ARG::clone_tree"
);
next_arg
=
&
tmp_link
;
root
=
clone
((
SEL_ARG
*
)
0
,
&
next_arg
);
next_arg
->
next
=
0
;
// Fix last link
tmp_link
.
next
->
prev
=
0
;
// Fix first link
root
->
use_count
=
0
;
return
root
;
DBUG_RETURN
(
root
)
;
}
/*****************************************************************************
...
...
@@ -1102,6 +1167,7 @@ static bool like_range(const char *ptr,uint ptr_length,char escape,
const
char
*
end
=
ptr
+
ptr_length
;
char
*
min_org
=
min_str
;
char
*
min_end
=
min_str
+
res_length
;
DBUG_ENTER
(
"like_range"
);
for
(;
ptr
!=
end
&&
min_str
!=
min_end
;
ptr
++
)
{
...
...
@@ -1125,7 +1191,7 @@ static bool like_range(const char *ptr,uint ptr_length,char escape,
*
min_str
++
=
' '
;
// Because if key compression
*
max_str
++
=
max_sort_chr
;
}
while
(
min_str
!=
min_end
);
return
0
;
DBUG_RETURN
(
0
)
;
}
*
min_str
++=
*
max_str
++
=
*
ptr
;
}
...
...
@@ -1137,7 +1203,7 @@ static bool like_range(const char *ptr,uint ptr_length,char escape,
while
(
min_str
!=
min_end
)
*
min_str
++
=
*
max_str
++
=
' '
;
// Because if key compression
return
0
;
DBUG_RETURN
(
0
)
;
}
...
...
@@ -1162,11 +1228,12 @@ static SEL_ARG *
sel_add
(
SEL_ARG
*
key1
,
SEL_ARG
*
key2
)
{
SEL_ARG
*
root
,
**
key_link
;
DBUG_ENTER
(
"sel_add"
);
if
(
!
key1
)
return
key2
;
DBUG_RETURN
(
key2
)
;
if
(
!
key2
)
return
key1
;
DBUG_RETURN
(
key1
)
;
key_link
=
&
root
;
while
(
key1
&&
key2
)
...
...
@@ -1185,7 +1252,7 @@ sel_add(SEL_ARG *key1,SEL_ARG *key2)
}
}
*
key_link
=
key1
?
key1
:
key2
;
return
root
;
DBUG_RETURN
(
root
)
;
}
#define CLONE_KEY1_MAYBE 1
...
...
@@ -1286,6 +1353,7 @@ and_all_keys(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag)
{
SEL_ARG
*
next
;
ulong
use_count
=
key1
->
use_count
;
DBUG_ENTER
(
"and_all_keys"
);
if
(
key1
->
elements
!=
1
)
{
...
...
@@ -1315,9 +1383,9 @@ and_all_keys(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag)
next
->
next_key_part
=
key2
;
}
if
(
!
key1
)
return
&
null_element
;
// Impossible ranges
DBUG_RETURN
(
&
null_element
)
;
// Impossible ranges
key1
->
use_count
++
;
return
key1
;
DBUG_RETURN
(
key1
)
;
}
...
...
@@ -1325,10 +1393,12 @@ and_all_keys(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag)
static
SEL_ARG
*
key_and
(
SEL_ARG
*
key1
,
SEL_ARG
*
key2
,
uint
clone_flag
)
{
DBUG_ENTER
(
"key_and"
);
if
(
!
key1
)
return
key2
;
DBUG_RETURN
(
key2
)
;
if
(
!
key2
)
return
key1
;
DBUG_RETURN
(
key1
)
;
if
(
key1
->
part
!=
key2
->
part
)
{
if
(
key1
->
part
>
key2
->
part
)
...
...
@@ -1340,7 +1410,7 @@ key_and(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag)
key1
->
use_count
--
;
if
(
key1
->
use_count
>
0
)
key1
=
key1
->
clone_tree
();
return
and_all_keys
(
key1
,
key2
,
clone_flag
);
DBUG_RETURN
(
and_all_keys
(
key1
,
key2
,
clone_flag
)
);
}
if
(((
clone_flag
&
CLONE_KEY2_MAYBE
)
&&
...
...
@@ -1366,16 +1436,16 @@ key_and(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag)
clone_flag
);
if
(
key1
->
next_key_part
&&
key1
->
next_key_part
->
type
==
SEL_ARG
::
IMPOSSIBLE
)
return
key1
;
DBUG_RETURN
(
key1
)
;
}
else
{
key1
->
maybe_smaller
();
if
(
key2
->
next_key_part
)
return
and_all_keys
(
key1
,
key2
,
clone_flag
);
DBUG_RETURN
(
and_all_keys
(
key1
,
key2
,
clone_flag
)
);
key2
->
use_count
--
;
// Key2 doesn't have a tree
}
return
key1
;
DBUG_RETURN
(
key1
)
;
}
key1
->
use_count
--
;
...
...
@@ -1414,32 +1484,36 @@ key_and(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag)
key1
->
free_tree
();
key2
->
free_tree
();
if
(
!
new_tree
)
return
&
null_element
;
// Impossible range
return
new_tree
;
DBUG_RETURN
(
&
null_element
)
;
// Impossible range
DBUG_RETURN
(
new_tree
)
;
}
static
bool
get_range
(
SEL_ARG
**
e1
,
SEL_ARG
**
e2
,
SEL_ARG
*
root1
)
{
DBUG_ENTER
(
"get_range"
);
(
*
e1
)
=
root1
->
find_range
(
*
e2
);
// first e1->min < e2->min
if
((
*
e1
)
->
cmp_max_to_min
(
*
e2
)
<
0
)
{
if
(
!
((
*
e1
)
=
(
*
e1
)
->
next
))
return
1
;
DBUG_RETURN
(
1
)
;
if
((
*
e1
)
->
cmp_min_to_max
(
*
e2
)
>
0
)
{
(
*
e2
)
=
(
*
e2
)
->
next
;
return
1
;
DBUG_RETURN
(
1
)
;
}
}
return
0
;
DBUG_RETURN
(
0
)
;
}
static
SEL_ARG
*
key_or
(
SEL_ARG
*
key1
,
SEL_ARG
*
key2
)
{
DBUG_ENTER
(
"key_or"
);
if
(
!
key1
)
{
if
(
key2
)
...
...
@@ -1447,13 +1521,13 @@ key_or(SEL_ARG *key1,SEL_ARG *key2)
key2
->
use_count
--
;
key2
->
free_tree
();
}
return
0
;
DBUG_RETURN
(
0
)
;
}
else
if
(
!
key2
)
{
key1
->
use_count
--
;
key1
->
free_tree
();
return
0
;
DBUG_RETURN
(
0
)
;
}
key1
->
use_count
--
;
key2
->
use_count
--
;
...
...
@@ -1462,7 +1536,7 @@ key_or(SEL_ARG *key1,SEL_ARG *key2)
{
key1
->
free_tree
();
key2
->
free_tree
();
return
0
;
// Can't optimize this
DBUG_RETURN
(
0
)
;
// Can't optimize this
}
// If one of the key is MAYBE_KEY then the found region may be bigger
...
...
@@ -1470,13 +1544,13 @@ key_or(SEL_ARG *key1,SEL_ARG *key2)
{
key2
->
free_tree
();
key1
->
use_count
++
;
return
key1
;
DBUG_RETURN
(
key1
)
;
}
if
(
key2
->
type
==
SEL_ARG
::
MAYBE_KEY
)
{
key1
->
free_tree
();
key2
->
use_count
++
;
return
key2
;
DBUG_RETURN
(
key2
)
;
}
if
(
key1
->
use_count
>
0
)
...
...
@@ -1541,8 +1615,8 @@ key_or(SEL_ARG *key1,SEL_ARG *key2)
tmp
->
max_flag
&
NO_MAX_RANGE
)
{
if
(
key1
->
maybe_flag
)
return
new
SEL_ARG
(
SEL_ARG
::
MAYBE_KEY
);
return
0
;
DBUG_RETURN
(
new
SEL_ARG
(
SEL_ARG
::
MAYBE_KEY
)
);
DBUG_RETURN
(
0
)
;
}
key2
->
increment_use_count
(
-
1
);
// Free not used tree
key2
=
key2
->
next
;
...
...
@@ -1588,8 +1662,8 @@ key_or(SEL_ARG *key1,SEL_ARG *key2)
for
(;
key2
;
key2
=
key2
->
next
)
key2
->
increment_use_count
(
-
1
);
// Free not used tree
if
(
key1
->
maybe_flag
)
return
new
SEL_ARG
(
SEL_ARG
::
MAYBE_KEY
);
return
0
;
DBUG_RETURN
(
new
SEL_ARG
(
SEL_ARG
::
MAYBE_KEY
)
);
DBUG_RETURN
(
0
)
;
}
}
key2
=
key2
->
next
;
...
...
@@ -1663,7 +1737,7 @@ end:
key2
=
next
;
}
key1
->
use_count
++
;
return
key1
;
DBUG_RETURN
(
key1
)
;
}
...
...
@@ -1671,31 +1745,33 @@ end:
static
bool
eq_tree
(
SEL_ARG
*
a
,
SEL_ARG
*
b
)
{
DBUG_ENTER
(
"eq_tree"
);
if
(
a
==
b
)
return
1
;
DBUG_RETURN
(
1
)
;
if
(
!
a
||
!
b
||
!
a
->
is_same
(
b
))
return
0
;
DBUG_RETURN
(
0
)
;
if
(
a
->
left
!=
&
null_element
&&
b
->
left
!=
&
null_element
)
{
if
(
!
eq_tree
(
a
->
left
,
b
->
left
))
return
0
;
DBUG_RETURN
(
0
)
;
}
else
if
(
a
->
left
!=
&
null_element
||
b
->
left
!=
&
null_element
)
return
0
;
DBUG_RETURN
(
0
)
;
if
(
a
->
right
!=
&
null_element
&&
b
->
right
!=
&
null_element
)
{
if
(
!
eq_tree
(
a
->
right
,
b
->
right
))
return
0
;
DBUG_RETURN
(
0
)
;
}
else
if
(
a
->
right
!=
&
null_element
||
b
->
right
!=
&
null_element
)
return
0
;
DBUG_RETURN
(
0
)
;
if
(
a
->
next_key_part
!=
b
->
next_key_part
)
{
// Sub range
if
(
!
a
->
next_key_part
!=
!
b
->
next_key_part
||
!
eq_tree
(
a
->
next_key_part
,
b
->
next_key_part
))
return
0
;
DBUG_RETURN
(
0
)
;
}
return
1
;
DBUG_RETURN
(
1
)
;
}
...
...
@@ -1703,6 +1779,7 @@ SEL_ARG *
SEL_ARG
::
insert
(
SEL_ARG
*
key
)
{
SEL_ARG
*
element
,
**
par
,
*
last_element
;
DBUG_ENTER
(
"SEL_ARG::insert"
);
LINT_INIT
(
par
);
LINT_INIT
(
last_element
);
for
(
element
=
this
;
element
!=
&
null_element
;
)
...
...
@@ -1739,7 +1816,7 @@ SEL_ARG::insert(SEL_ARG *key)
root
->
use_count
=
this
->
use_count
;
// copy root info
root
->
elements
=
this
->
elements
+
1
;
root
->
maybe_flag
=
this
->
maybe_flag
;
return
root
;
DBUG_RETURN
(
root
)
;
}
...
...
@@ -1752,14 +1829,15 @@ SEL_ARG *
SEL_ARG
::
find_range
(
SEL_ARG
*
key
)
{
SEL_ARG
*
element
=
this
,
*
found
=
0
;
DBUG_ENTER
(
"SEL_ARG::find_range"
);
for
(;;)
{
if
(
element
==
&
null_element
)
return
found
;
DBUG_RETURN
(
found
)
;
int
cmp
=
element
->
cmp_min_to_min
(
key
);
if
(
cmp
==
0
)
return
element
;
DBUG_RETURN
(
element
)
;
if
(
cmp
<
0
)
{
found
=
element
;
...
...
@@ -1768,6 +1846,7 @@ SEL_ARG::find_range(SEL_ARG *key)
else
element
=
element
->
left
;
}
DBUG_RETURN
(
NULL
);
// impossible
}
...
...
@@ -1781,6 +1860,8 @@ SEL_ARG::tree_delete(SEL_ARG *key)
{
enum
leaf_color
remove_color
;
SEL_ARG
*
root
,
*
nod
,
**
par
,
*
fix_par
;
DBUG_ENTER
(
"SEL_ARG::tree_delete"
);
root
=
this
;
this
->
parent
=
0
;
/* Unlink from list */
...
...
@@ -1828,7 +1909,7 @@ SEL_ARG::tree_delete(SEL_ARG *key)
}
if
(
root
==
&
null_element
)
return
0
;
// Maybe root later
DBUG_RETURN
(
0
)
;
// Maybe root later
if
(
remove_color
==
BLACK
)
root
=
rb_delete_fixup
(
root
,
nod
,
fix_par
);
test_rb_tree
(
root
,
root
->
parent
);
...
...
@@ -1836,7 +1917,7 @@ SEL_ARG::tree_delete(SEL_ARG *key)
root
->
use_count
=
this
->
use_count
;
// Fix root counters
root
->
elements
=
this
->
elements
-
1
;
root
->
maybe_flag
=
this
->
maybe_flag
;
return
root
;
DBUG_RETURN
(
root
)
;
}
...
...
@@ -1845,6 +1926,8 @@ SEL_ARG::tree_delete(SEL_ARG *key)
static
void
left_rotate
(
SEL_ARG
**
root
,
SEL_ARG
*
leaf
)
{
SEL_ARG
*
y
=
leaf
->
right
;
DBUG_ENTER
(
"left_rotate"
);
leaf
->
right
=
y
->
left
;
if
(
y
->
left
!=
&
null_element
)
y
->
left
->
parent
=
leaf
;
...
...
@@ -1854,11 +1937,14 @@ static void left_rotate(SEL_ARG **root,SEL_ARG *leaf)
*
leaf
->
parent_ptr
()
=
y
;
y
->
left
=
leaf
;
leaf
->
parent
=
y
;
DBUG_VOID_RETURN
;
}
static
void
right_rotate
(
SEL_ARG
**
root
,
SEL_ARG
*
leaf
)
{
SEL_ARG
*
y
=
leaf
->
left
;
DBUG_ENTER
(
"right_rotate"
);
leaf
->
left
=
y
->
right
;
if
(
y
->
right
!=
&
null_element
)
y
->
right
->
parent
=
leaf
;
...
...
@@ -1868,6 +1954,7 @@ static void right_rotate(SEL_ARG **root,SEL_ARG *leaf)
*
leaf
->
parent_ptr
()
=
y
;
y
->
right
=
leaf
;
leaf
->
parent
=
y
;
DBUG_VOID_RETURN
;
}
...
...
@@ -1875,6 +1962,8 @@ SEL_ARG *
SEL_ARG
::
rb_insert
(
SEL_ARG
*
leaf
)
{
SEL_ARG
*
y
,
*
par
,
*
par2
,
*
root
;
DBUG_ENTER
(
"SEL_ARG::rb_insert"
);
root
=
this
;
root
->
parent
=
0
;
leaf
->
color
=
RED
;
...
...
@@ -1929,13 +2018,15 @@ SEL_ARG::rb_insert(SEL_ARG *leaf)
}
root
->
color
=
BLACK
;
test_rb_tree
(
root
,
root
->
parent
);
return
root
;
DBUG_RETURN
(
root
)
;
}
SEL_ARG
*
rb_delete_fixup
(
SEL_ARG
*
root
,
SEL_ARG
*
key
,
SEL_ARG
*
par
)
{
SEL_ARG
*
x
,
*
w
;
DBUG_ENTER
(
"*rb_delete_fixup"
);
root
->
parent
=
0
;
x
=
key
;
...
...
@@ -2008,7 +2099,7 @@ SEL_ARG *rb_delete_fixup(SEL_ARG *root,SEL_ARG *key,SEL_ARG *par)
par
=
x
->
parent
;
}
x
->
color
=
SEL_ARG
::
BLACK
;
return
root
;
DBUG_RETURN
(
root
)
;
}
...
...
@@ -2018,41 +2109,44 @@ SEL_ARG *rb_delete_fixup(SEL_ARG *root,SEL_ARG *key,SEL_ARG *par)
int
test_rb_tree
(
SEL_ARG
*
element
,
SEL_ARG
*
parent
)
{
int
count_l
,
count_r
;
DBUG_ENTER
(
"test_rb_tree"
);
if
(
element
==
&
null_element
)
return
0
;
// Found end of tree
DBUG_RETURN
(
0
)
;
// Found end of tree
if
(
element
->
parent
!=
parent
)
{
sql_print_error
(
"Wrong tree: Parent doesn't point at parent"
);
return
-
1
;
DBUG_RETURN
(
-
1
)
;
}
if
(
element
->
color
==
SEL_ARG
::
RED
&&
(
element
->
left
->
color
==
SEL_ARG
::
RED
||
element
->
right
->
color
==
SEL_ARG
::
RED
))
{
sql_print_error
(
"Wrong tree: Found two red in a row"
);
return
-
1
;
DBUG_RETURN
(
-
1
)
;
}
if
(
element
->
left
==
element
->
right
&&
element
->
left
!=
&
null_element
)
{
// Dummy test
sql_print_error
(
"Wrong tree: Found right == left"
);
return
-
1
;
DBUG_RETURN
(
-
1
)
;
}
count_l
=
test_rb_tree
(
element
->
left
,
element
);
count_r
=
test_rb_tree
(
element
->
right
,
element
);
if
(
count_l
>=
0
&&
count_r
>=
0
)
{
if
(
count_l
==
count_r
)
return
count_l
+
(
element
->
color
==
SEL_ARG
::
BLACK
);
DBUG_RETURN
(
count_l
+
(
element
->
color
==
SEL_ARG
::
BLACK
)
);
sql_print_error
(
"Wrong tree: Incorrect black-count: %d - %d"
,
count_l
,
count_r
);
}
return
-
1
;
// Error, no more warnings
DBUG_RETURN
(
-
1
)
;
// Error, no more warnings
}
static
ulong
count_key_part_usage
(
SEL_ARG
*
root
,
SEL_ARG
*
key
)
{
ulong
count
=
0
;
DBUG_ENTER
(
"count_key_part_usage"
);
for
(
root
=
root
->
first
();
root
;
root
=
root
->
next
)
{
if
(
root
->
next_key_part
)
...
...
@@ -2063,19 +2157,21 @@ static ulong count_key_part_usage(SEL_ARG *root, SEL_ARG *key)
count
+=
count_key_part_usage
(
root
->
next_key_part
,
key
);
}
}
return
count
;
DBUG_RETURN
(
count
)
;
}
void
SEL_ARG
::
test_use_count
(
SEL_ARG
*
root
)
{
DBUG_ENTER
(
"SEL_ARG::test_use_count"
);
if
(
this
==
root
&&
use_count
!=
1
)
{
sql_print_error
(
"Use_count: Wrong count %lu for root"
,
use_count
);
return
;
DBUG_VOID_RETURN
;
}
if
(
this
->
type
!=
SEL_ARG
::
KEY_RANGE
)
return
;
DBUG_VOID_RETURN
;
uint
e_count
=
0
;
for
(
SEL_ARG
*
pos
=
first
();
pos
;
pos
=
pos
->
next
)
{
...
...
@@ -2087,7 +2183,7 @@ void SEL_ARG::test_use_count(SEL_ARG *root)
{
sql_print_error
(
"Use_count: Wrong count for key at %lx, %lu should be %lu"
,
pos
,
pos
->
next_key_part
->
use_count
,
count
);
return
;
DBUG_VOID_RETURN
;
}
pos
->
next_key_part
->
test_use_count
(
root
);
}
...
...
@@ -2095,6 +2191,7 @@ void SEL_ARG::test_use_count(SEL_ARG *root)
if
(
e_count
!=
elements
)
sql_print_error
(
"Wrong use count: %u for tree at %lx"
,
e_count
,
(
gptr
)
this
);
DBUG_VOID_RETURN
;
}
#endif
...
...
@@ -2136,6 +2233,7 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
uint
max_key_flag
)
{
ha_rows
records
=
0
,
tmp
;
DBUG_ENTER
(
"check_quick_keys"
);
param
->
max_key_part
=
max
(
param
->
max_key_part
,
key_tree
->
part
);
if
(
key_tree
->
left
!=
&
null_element
)
...
...
@@ -2143,7 +2241,7 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
records
=
check_quick_keys
(
param
,
idx
,
key_tree
->
left
,
min_key
,
min_key_flag
,
max_key
,
max_key_flag
);
if
(
records
==
HA_POS_ERROR
)
// Impossible
return
records
;
DBUG_RETURN
(
records
)
;
}
uint
tmp_min_flag
,
tmp_max_flag
,
keynr
;
...
...
@@ -2206,17 +2304,17 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
HA_READ_BEFORE_KEY
:
HA_READ_AFTER_KEY
));
end:
if
(
tmp
==
HA_POS_ERROR
)
// Impossible range
return
tmp
;
DBUG_RETURN
(
tmp
)
;
records
+=
tmp
;
if
(
key_tree
->
right
!=
&
null_element
)
{
tmp
=
check_quick_keys
(
param
,
idx
,
key_tree
->
right
,
min_key
,
min_key_flag
,
max_key
,
max_key_flag
);
if
(
tmp
==
HA_POS_ERROR
)
return
tmp
;
DBUG_RETURN
(
tmp
)
;
records
+=
tmp
;
}
return
records
;
DBUG_RETURN
(
records
)
;
}
...
...
@@ -2262,12 +2360,13 @@ get_quick_keys(PARAM *param,QUICK_SELECT *quick,KEY_PART *key,
{
QUICK_RANGE
*
range
;
uint
flag
;
DBUG_ENTER
(
"get_quick_keys"
);
if
(
key_tree
->
left
!=
&
null_element
)
{
if
(
get_quick_keys
(
param
,
quick
,
key
,
key_tree
->
left
,
min_key
,
min_key_flag
,
max_key
,
max_key_flag
))
return
1
;
DBUG_RETURN
(
1
)
;
}
char
*
tmp_min_key
=
min_key
,
*
tmp_max_key
=
max_key
;
key_tree
->
store
(
key
[
key_tree
->
part
].
part_length
,
...
...
@@ -2284,7 +2383,7 @@ get_quick_keys(PARAM *param,QUICK_SELECT *quick,KEY_PART *key,
if
(
get_quick_keys
(
param
,
quick
,
key
,
key_tree
->
next_key_part
,
tmp_min_key
,
min_key_flag
|
key_tree
->
min_flag
,
tmp_max_key
,
max_key_flag
|
key_tree
->
max_flag
))
return
1
;
DBUG_RETURN
(
1
)
;
goto
end
;
// Ugly, but efficient
}
{
...
...
@@ -2342,15 +2441,15 @@ get_quick_keys(PARAM *param,QUICK_SELECT *quick,KEY_PART *key,
set_if_bigger
(
quick
->
max_used_key_length
,
range
->
min_length
);
set_if_bigger
(
quick
->
max_used_key_length
,
range
->
max_length
);
if
(
!
range
)
// Not enough memory
return
1
;
DBUG_RETURN
(
1
)
;
quick
->
ranges
.
push_back
(
range
);
end:
if
(
key_tree
->
right
!=
&
null_element
)
return
get_quick_keys
(
param
,
quick
,
key
,
key_tree
->
right
,
DBUG_RETURN
(
get_quick_keys
(
param
,
quick
,
key
,
key_tree
->
right
,
min_key
,
min_key_flag
,
max_key
,
max_key_flag
);
return
0
;
max_key
,
max_key_flag
)
)
;
DBUG_RETURN
(
0
)
;
}
/*
...
...
@@ -2359,17 +2458,19 @@ get_quick_keys(PARAM *param,QUICK_SELECT *quick,KEY_PART *key,
bool
QUICK_SELECT
::
unique_key_range
()
{
DBUG_ENTER
(
"QUICK_SELECT::unique_key_range"
);
if
(
ranges
.
elements
==
1
)
{
QUICK_RANGE
*
tmp
;
if
(((
tmp
=
ranges
.
head
())
->
flag
&
(
EQ_RANGE
|
NULL_RANGE
))
==
EQ_RANGE
)
{
KEY
*
key
=
head
->
key_info
+
index
;
return
((
key
->
flags
&
HA_NOSAME
)
&&
key
->
key_length
==
tmp
->
min_length
);
DBUG_RETURN
(
((
key
->
flags
&
HA_NOSAME
)
&&
key
->
key_length
==
tmp
->
min_length
)
)
;
}
}
return
0
;
DBUG_RETURN
(
0
)
;
}
...
...
@@ -2377,6 +2478,8 @@ bool QUICK_SELECT::unique_key_range()
static
bool
null_part_in_key
(
KEY_PART
*
key_part
,
const
char
*
key
,
uint
length
)
{
DBUG_ENTER
(
"null_part_in_key"
);
for
(
const
char
*
end
=
key
+
length
;
key
<
end
;
key
+=
key_part
++->
part_length
)
...
...
@@ -2384,10 +2487,10 @@ static bool null_part_in_key(KEY_PART *key_part, const char *key, uint length)
if
(
key_part
->
null_bit
)
{
if
(
*
key
++
)
return
1
;
DBUG_RETURN
(
1
)
;
}
}
return
0
;
DBUG_RETURN
(
0
)
;
}
/****************************************************************************
...
...
@@ -2396,6 +2499,8 @@ static bool null_part_in_key(KEY_PART *key_part, const char *key, uint length)
QUICK_SELECT
*
get_quick_select_for_ref
(
TABLE
*
table
,
TABLE_REF
*
ref
)
{
DBUG_ENTER
(
"*get_quick_select_for_ref"
);
table
->
file
->
index_end
();
// Remove old cursor
QUICK_SELECT
*
quick
=
new
QUICK_SELECT
(
table
,
ref
->
key
,
1
);
KEY
*
key_info
=
&
table
->
key_info
[
ref
->
key
];
...
...
@@ -2403,7 +2508,7 @@ QUICK_SELECT *get_quick_select_for_ref(TABLE *table, TABLE_REF *ref)
uint
part
;
if
(
!
quick
)
return
0
;
DBUG_RETURN
(
0
)
;
QUICK_RANGE
*
range
=
new
QUICK_RANGE
();
if
(
!
range
||
cp_buffer_from_ref
(
ref
))
goto
err
;
...
...
@@ -2426,11 +2531,11 @@ QUICK_SELECT *get_quick_select_for_ref(TABLE *table, TABLE_REF *ref)
key_part
->
null_bit
=
key_info
->
key_part
[
part
].
null_bit
;
}
if
(
!
quick
->
ranges
.
push_back
(
range
))
return
quick
;
DBUG_RETURN
(
quick
)
;
err:
delete
quick
;
return
0
;
DBUG_RETURN
(
0
)
;
}
/* get next possible record using quick-struct */
...
...
@@ -2491,6 +2596,7 @@ int QUICK_SELECT::get_next()
}
range
=
0
;
// To next range
}
DBUG_RETURN
(
0
);
// impossible
}
/* compare if found key is over max-value */
...
...
@@ -2498,8 +2604,10 @@ int QUICK_SELECT::get_next()
int
QUICK_SELECT
::
cmp_next
(
QUICK_RANGE
*
range_arg
)
{
DBUG_ENTER
(
"QUICK_SELECT::cmp_next"
);
if
(
range_arg
->
flag
&
NO_MAX_RANGE
)
return
(
0
);
/* key can't be to large */
DBUG_RETURN
(
0
);
/* key can't be to large */
KEY_PART
*
key_part
=
key_parts
;
for
(
char
*
key
=
range_arg
->
max_key
,
*
end
=
key
+
range_arg
->
max_length
;
...
...
@@ -2512,18 +2620,18 @@ int QUICK_SELECT::cmp_next(QUICK_RANGE *range_arg)
if
(
*
key
++
)
{
if
(
!
key_part
->
field
->
is_null
())
return
1
;
DBUG_RETURN
(
1
)
;
continue
;
}
else
if
(
key_part
->
field
->
is_null
())
return
0
;
DBUG_RETURN
(
0
)
;
}
if
((
cmp
=
key_part
->
field
->
key_cmp
((
byte
*
)
key
,
key_part
->
part_length
))
<
0
)
return
0
;
DBUG_RETURN
(
0
)
;
if
(
cmp
>
0
)
return
1
;
DBUG_RETURN
(
1
)
;
}
return
(
range_arg
->
flag
&
NEAR_MAX
)
?
1
:
0
;
// Exact match
DBUG_RETURN
((
range_arg
->
flag
&
NEAR_MAX
)
?
1
:
0
)
;
// Exact match
}
...
...
@@ -2542,6 +2650,7 @@ QUICK_SELECT_DESC::QUICK_SELECT_DESC(QUICK_SELECT *q, uint used_key_parts)
{
bool
not_read_after_key
=
file
->
table_flags
()
&
HA_NOT_READ_AFTER_KEY
;
QUICK_RANGE
*
r
;
DBUG_ENTER
(
"QUICK_SELECT_DESC::QUICK_SELECT_DESC"
);
it
.
rewind
();
for
(
r
=
it
++
;
r
;
r
=
it
++
)
...
...
@@ -2553,7 +2662,7 @@ QUICK_SELECT_DESC::QUICK_SELECT_DESC(QUICK_SELECT *q, uint used_key_parts)
it
.
rewind
();
// Reset range
error
=
HA_ERR_UNSUPPORTED
;
dont_free
=
1
;
// Don't free memory from 'q'
return
;
DBUG_VOID_RETURN
;
}
}
/* Remove EQ_RANGE flag for keys that are not using the full key */
...
...
@@ -2566,6 +2675,7 @@ QUICK_SELECT_DESC::QUICK_SELECT_DESC(QUICK_SELECT *q, uint used_key_parts)
rev_it
.
rewind
();
q
->
dont_free
=
1
;
// Don't free shared mem
delete
q
;
DBUG_VOID_RETURN
;
}
...
...
@@ -2653,6 +2763,7 @@ int QUICK_SELECT_DESC::get_next()
}
range
=
0
;
// To next range
}
DBUG_RETURN
(
0
);
// impossible
}
...
...
@@ -2662,8 +2773,10 @@ int QUICK_SELECT_DESC::get_next()
int
QUICK_SELECT_DESC
::
cmp_prev
(
QUICK_RANGE
*
range_arg
)
{
DBUG_ENTER
(
"QUICK_SELECT_DESC::cmp_prev"
);
if
(
range_arg
->
flag
&
NO_MIN_RANGE
)
return
(
0
);
/* key can't be to small */
DBUG_RETURN
(
0
);
/* key can't be to small */
KEY_PART
*
key_part
=
key_parts
;
for
(
char
*
key
=
range_arg
->
min_key
,
*
end
=
key
+
range_arg
->
min_length
;
...
...
@@ -2678,19 +2791,19 @@ int QUICK_SELECT_DESC::cmp_prev(QUICK_RANGE *range_arg)
{
// the range is expecting a null value
if
(
!
key_part
->
field
->
is_null
())
return
0
;
// not null -- still inside the range
DBUG_RETURN
(
0
)
;
// not null -- still inside the range
continue
;
// null -- exact match, go to next key part
}
else
if
(
key_part
->
field
->
is_null
())
return
1
;
// null -- outside the range
DBUG_RETURN
(
1
)
;
// null -- outside the range
}
if
((
cmp
=
key_part
->
field
->
key_cmp
((
byte
*
)
key
,
key_part
->
part_length
))
>
0
)
return
0
;
DBUG_RETURN
(
0
)
;
if
(
cmp
<
0
)
return
1
;
DBUG_RETURN
(
1
)
;
}
return
(
range_arg
->
flag
&
NEAR_MIN
)
?
1
:
0
;
// Exact match
DBUG_RETURN
((
range_arg
->
flag
&
NEAR_MIN
)
?
1
:
0
)
;
// Exact match
}
...
...
@@ -2701,9 +2814,11 @@ int QUICK_SELECT_DESC::cmp_prev(QUICK_RANGE *range_arg)
bool
QUICK_SELECT_DESC
::
range_reads_after_key
(
QUICK_RANGE
*
range_arg
)
{
return
((
range_arg
->
flag
&
(
NO_MAX_RANGE
|
NEAR_MAX
))
||
DBUG_ENTER
(
"QUICK_SELECT_DESC::range_reads_after_key"
);
DBUG_RETURN
(((
range_arg
->
flag
&
(
NO_MAX_RANGE
|
NEAR_MAX
))
||
!
(
range_arg
->
flag
&
EQ_RANGE
)
||
head
->
key_info
[
index
].
key_length
!=
range_arg
->
max_length
)
?
1
:
0
;
head
->
key_info
[
index
].
key_length
!=
range_arg
->
max_length
)
?
1
:
0
)
;
}
...
...
@@ -2715,6 +2830,7 @@ bool QUICK_SELECT_DESC::test_if_null_range(QUICK_RANGE *range_arg,
uint
offset
,
end
;
KEY_PART
*
key_part
=
key_parts
,
*
key_part_end
=
key_part
+
used_key_parts
;
DBUG_ENTER
(
"QUICK_SELECT_DESC::test_if_null_range"
);
for
(
offset
=
0
,
end
=
min
(
range_arg
->
min_length
,
range_arg
->
max_length
)
;
offset
<
end
&&
key_part
!=
key_part_end
;
...
...
@@ -2729,7 +2845,7 @@ bool QUICK_SELECT_DESC::test_if_null_range(QUICK_RANGE *range_arg,
continue
;
}
if
(
null_length
&&
range_arg
->
min_key
[
offset
])
return
1
;
// min_key is null and max_key isn't
DBUG_RETURN
(
1
)
;
// min_key is null and max_key isn't
// Range doesn't cover NULL. This is ok if there is no more null parts
break
;
}
...
...
@@ -2742,7 +2858,7 @@ bool QUICK_SELECT_DESC::test_if_null_range(QUICK_RANGE *range_arg,
if
(
key_part
!=
key_part_end
&&
key_part
->
null_bit
)
{
if
(
offset
>=
range_arg
->
min_length
||
range_arg
->
min_key
[
offset
])
return
1
;
// Could be null
DBUG_RETURN
(
1
)
;
// Could be null
key_part
++
;
}
/*
...
...
@@ -2751,8 +2867,8 @@ bool QUICK_SELECT_DESC::test_if_null_range(QUICK_RANGE *range_arg,
*/
for
(;
key_part
!=
key_part_end
;
key_part
++
)
if
(
key_part
->
null_bit
)
return
1
;
// Covers null part
return
0
;
DBUG_RETURN
(
1
)
;
// Covers null part
DBUG_RETURN
(
0
)
;
}
...
...
@@ -2770,6 +2886,7 @@ print_key(KEY_PART *key_part,const char *key,uint used_length)
{
char
buff
[
1024
];
String
tmp
(
buff
,
sizeof
(
buff
));
DBUG_ENTER
(
"print_key"
);
for
(
uint
length
=
0
;
length
<
used_length
;
...
...
@@ -2793,6 +2910,7 @@ print_key(KEY_PART *key_part,const char *key,uint used_length)
field
->
val_str
(
&
tmp
,
&
tmp
);
fwrite
(
tmp
.
ptr
(),
sizeof
(
char
),
tmp
.
length
(),
DBUG_FILE
);
}
DBUG_VOID_RETURN
;
}
static
void
print_quick
(
QUICK_SELECT
*
quick
,
key_map
needed_reg
)
...
...
sql/sql_select.cc
View file @
cd6bf73f
...
...
@@ -156,6 +156,7 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
{
int
res
;
register
SELECT_LEX
*
select_lex
=
&
lex
->
select_lex
;
DBUG_ENTER
(
"handle_select"
);
#ifdef DISABLED_UNTIL_REWRITTEN_IN_4_1
if
(
lex
->
olap
)
...
...
@@ -168,7 +169,7 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
if
(
sl
->
olap
!=
UNSPECIFIED_OLAP_TYPE
)
{
if
((
error
=
handle_olaps
(
lex
,
sl
)))
return
error
;
DBUG_RETURN
(
error
)
;
lex
->
last_selects
->
next
=
sl_next
;
}
}
...
...
@@ -190,7 +191,7 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
if
(
res
&&
result
)
result
->
abort
();
delete
result
;
return
res
;
DBUG_RETURN
(
res
)
;
}
...
...
@@ -1266,10 +1267,12 @@ static KEY_FIELD *
merge_key_fields
(
KEY_FIELD
*
start
,
KEY_FIELD
*
new_fields
,
KEY_FIELD
*
end
,
uint
and_level
)
{
DBUG_ENTER
(
"merge_key_fields"
);
if
(
start
==
new_fields
)
return
start
;
// Impossible or
DBUG_RETURN
(
start
)
;
// Impossible or
if
(
new_fields
==
end
)
return
start
;
// No new fields, skip all
DBUG_RETURN
(
start
)
;
// No new fields, skip all
KEY_FIELD
*
first_free
=
new_fields
;
...
...
@@ -1316,7 +1319,7 @@ merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end,
}
old
++
;
}
return
first_free
;
DBUG_RETURN
(
first_free
)
;
}
...
...
@@ -1326,12 +1329,14 @@ add_key_field(KEY_FIELD **key_fields,uint and_level,
table_map
usable_tables
)
{
bool
exists_optimize
=
0
;
DBUG_ENTER
(
"add_key_field"
);
if
(
!
(
field
->
flags
&
PART_KEY_FLAG
))
{
// Don't remove column IS NULL on a LEFT JOIN table
if
(
!
eq_func
||
!
value
||
value
->
type
()
!=
Item
::
NULL_ITEM
||
!
field
->
table
->
maybe_null
||
field
->
null_ptr
)
return
;
// Not a key. Skip it
DBUG_VOID_RETURN
;
// Not a key. Skip it
exists_optimize
=
1
;
}
else
...
...
@@ -1339,12 +1344,12 @@ add_key_field(KEY_FIELD **key_fields,uint and_level,
table_map
used_tables
=
0
;
if
(
value
&&
(
used_tables
=
value
->
used_tables
())
&
(
field
->
table
->
map
|
RAND_TABLE_BIT
))
return
;
DBUG_VOID_RETURN
;
if
(
!
(
usable_tables
&
field
->
table
->
map
))
{
if
(
!
eq_func
||
!
value
||
value
->
type
()
!=
Item
::
NULL_ITEM
||
!
field
->
table
->
maybe_null
||
field
->
null_ptr
)
return
;
// Can't use left join optimize
DBUG_VOID_RETURN
;
// Can't use left join optimize
exists_optimize
=
1
;
}
else
...
...
@@ -1357,7 +1362,7 @@ add_key_field(KEY_FIELD **key_fields,uint and_level,
if
(
!
value
)
{
// Probably BETWEEN or IN
stat
[
0
].
const_keys
|=
possible_keys
;
return
;
// Can't be used as eq key
DBUG_VOID_RETURN
;
// Can't be used as eq key
}
/* Save the following cases:
...
...
@@ -1378,7 +1383,7 @@ add_key_field(KEY_FIELD **key_fields,uint and_level,
field
->
result_type
()
==
STRING_RESULT
&&
value
->
result_type
()
!=
STRING_RESULT
&&
field
->
cmp_type
()
!=
value
->
result_type
())
return
;
DBUG_VOID_RETURN
;
}
}
/* Store possible eq field */
...
...
@@ -1388,6 +1393,7 @@ add_key_field(KEY_FIELD **key_fields,uint and_level,
(
*
key_fields
)
->
level
=
(
*
key_fields
)
->
const_level
=
and_level
;
(
*
key_fields
)
->
exists_optimize
=
exists_optimize
;
(
*
key_fields
)
++
;
DBUG_VOID_RETURN
;
}
...
...
@@ -1395,6 +1401,8 @@ static void
add_key_fields
(
JOIN_TAB
*
stat
,
KEY_FIELD
**
key_fields
,
uint
*
and_level
,
COND
*
cond
,
table_map
usable_tables
)
{
DBUG_ENTER
(
"add_key_fields"
);
if
(
cond
->
type
()
==
Item_func
::
COND_ITEM
)
{
List_iterator_fast
<
Item
>
li
(
*
((
Item_cond
*
)
cond
)
->
argument_list
());
...
...
@@ -1427,12 +1435,12 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
*
key_fields
,
++
(
*
and_level
));
}
}
return
;
DBUG_VOID_RETURN
;
}
/* If item is of type 'field op field/constant' add it to key_fields */
if
(
cond
->
type
()
!=
Item
::
FUNC_ITEM
)
return
;
DBUG_VOID_RETURN
;
Item_func
*
cond_func
=
(
Item_func
*
)
cond
;
switch
(
cond_func
->
select_optimize
())
{
case
Item_func
:
:
OPTIMIZE_NONE
:
...
...
@@ -1476,7 +1484,7 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
}
break
;
}
return
;
DBUG_VOID_RETURN
;
}
/*
...
...
@@ -1488,8 +1496,10 @@ static uint
max_part_bit
(
key_map
bits
)
{
uint
found
;
DBUG_ENTER
(
"max_part_bit"
);
for
(
found
=
0
;
bits
&
1
;
found
++
,
bits
>>=
1
)
;
return
found
;
DBUG_RETURN
(
found
)
;
}
...
...
@@ -1499,6 +1509,7 @@ add_key_part(DYNAMIC_ARRAY *keyuse_array,KEY_FIELD *key_field)
Field
*
field
=
key_field
->
field
;
TABLE
*
form
=
field
->
table
;
KEYUSE
keyuse
;
DBUG_ENTER
(
"add_key_part"
);
if
(
key_field
->
eq_func
&&
!
key_field
->
exists_optimize
)
{
...
...
@@ -1528,6 +1539,7 @@ add_key_part(DYNAMIC_ARRAY *keyuse_array,KEY_FIELD *key_field)
if
(
key_field
->
val
->
type
()
==
Item
::
NULL_ITEM
&&
!
key_field
->
field
->
real_maybe_null
())
key_field
->
field
->
table
->
reginfo
.
not_exists_optimize
=
1
;
DBUG_VOID_RETURN
;
}
static
void
...
...
@@ -1535,9 +1547,10 @@ add_ft_keys(DYNAMIC_ARRAY *keyuse_array,
JOIN_TAB
*
stat
,
COND
*
cond
,
table_map
usable_tables
)
{
Item_func_match
*
cond_func
=
NULL
;
DBUG_ENTER
(
"add_ft_keys"
);
if
(
!
cond
)
return
;
DBUG_VOID_RETURN
;
if
(
cond
->
type
()
==
Item
::
FUNC_ITEM
)
{
...
...
@@ -1589,7 +1602,7 @@ add_ft_keys(DYNAMIC_ARRAY *keyuse_array,
}
if
(
!
cond_func
||
cond_func
->
key
==
NO_SUCH_KEY
)
return
;
DBUG_VOID_RETURN
;
KEYUSE
keyuse
;
...
...
@@ -1600,18 +1613,21 @@ add_ft_keys(DYNAMIC_ARRAY *keyuse_array,
keyuse
.
keypart
=
FT_KEYPART
;
keyuse
.
used_tables
=
cond_func
->
key_item
()
->
used_tables
();
VOID
(
insert_dynamic
(
keyuse_array
,(
gptr
)
&
keyuse
));
DBUG_VOID_RETURN
;
}
static
int
sort_keyuse
(
KEYUSE
*
a
,
KEYUSE
*
b
)
{
DBUG_ENTER
(
"sort_keyuse"
);
if
(
a
->
table
->
tablenr
!=
b
->
table
->
tablenr
)
return
(
int
)
(
a
->
table
->
tablenr
-
b
->
table
->
tablenr
);
DBUG_RETURN
((
int
)
(
a
->
table
->
tablenr
-
b
->
table
->
tablenr
)
);
if
(
a
->
key
!=
b
->
key
)
return
(
int
)
(
a
->
key
-
b
->
key
);
DBUG_RETURN
((
int
)
(
a
->
key
-
b
->
key
)
);
if
(
a
->
keypart
!=
b
->
keypart
)
return
(
int
)
(
a
->
keypart
-
b
->
keypart
);
return
test
(
a
->
used_tables
)
-
test
(
b
->
used_tables
);
// Place const first
DBUG_RETURN
((
int
)
(
a
->
keypart
-
b
->
keypart
)
);
DBUG_RETURN
(
test
(
a
->
used_tables
)
-
test
(
b
->
used_tables
)
);
// Place const first
}
...
...
@@ -1626,13 +1642,14 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
uint
tables
,
COND
*
cond
,
table_map
normal_tables
)
{
uint
and_level
,
i
,
found_eq_constant
;
DBUG_ENTER
(
"update_ref_and_keys"
);
{
KEY_FIELD
*
key_fields
,
*
end
;
if
(
!
(
key_fields
=
(
KEY_FIELD
*
)
thd
->
alloc
(
sizeof
(
key_fields
[
0
])
*
(
thd
->
cond_count
+
1
)
*
2
)))
return
TRUE
;
/* purecov: inspected */
DBUG_RETURN
(
TRUE
)
;
/* purecov: inspected */
and_level
=
0
;
end
=
key_fields
;
if
(
cond
)
add_key_fields
(
join_tab
,
&
end
,
&
and_level
,
cond
,
normal_tables
);
...
...
@@ -1645,7 +1662,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
}
}
if
(
my_init_dynamic_array
(
keyuse
,
sizeof
(
KEYUSE
),
20
,
64
))
return
TRUE
;
DBUG_RETURN
(
TRUE
)
;
/* fill keyuse with found key parts */
for
(
KEY_FIELD
*
field
=
key_fields
;
field
!=
end
;
field
++
)
add_key_part
(
keyuse
,
field
);
...
...
@@ -1704,7 +1721,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
VOID
(
set_dynamic
(
keyuse
,(
gptr
)
&
end
,
i
));
keyuse
->
elements
=
i
;
}
return
FALSE
;
DBUG_RETURN
(
FALSE
)
;
}
...
...
@@ -1718,6 +1735,8 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
static
void
set_position
(
JOIN
*
join
,
uint
idx
,
JOIN_TAB
*
table
,
KEYUSE
*
key
)
{
DBUG_ENTER
(
"set_position"
);
join
->
positions
[
idx
].
table
=
table
;
join
->
positions
[
idx
].
key
=
key
;
join
->
positions
[
idx
].
records_read
=
1.0
;
/* This is a const table */
...
...
@@ -1732,6 +1751,7 @@ set_position(JOIN *join,uint idx,JOIN_TAB *table,KEYUSE *key)
next
=
tmp
;
}
join
->
best_ref
[
idx
]
=
table
;
DBUG_VOID_RETURN
;
}
...
...
@@ -1752,6 +1772,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
ulong
rec
;
double
tmp
;
THD
*
thd
=
current_thd
;
DBUG_ENTER
(
"find_best"
);
if
(
!
rest_tables
)
{
...
...
@@ -1768,10 +1789,10 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
sizeof
(
POSITION
)
*
idx
);
join
->
best_read
=
read_time
;
}
return
;
DBUG_VOID_RETURN
;
}
if
(
read_time
+
record_count
/
(
double
)
TIME_FOR_COMPARE
>=
join
->
best_read
)
return
;
/* Found better before */
DBUG_VOID_RETURN
;
/* Found better before */
JOIN_TAB
*
s
;
double
best_record_count
=
DBL_MAX
,
best_read_time
=
DBL_MAX
;
...
...
@@ -2068,6 +2089,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
break
;
// Don't test all combinations
}
}
DBUG_VOID_RETURN
;
}
...
...
@@ -2078,6 +2100,8 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
static
void
calc_used_field_length
(
THD
*
thd
,
JOIN_TAB
*
join_tab
)
{
uint
null_fields
,
blobs
,
fields
,
rec_length
;
DBUG_ENTER
(
"calc_used_field_length"
);
null_fields
=
blobs
=
fields
=
rec_length
=
0
;
Field
**
f_ptr
,
*
field
;
...
...
@@ -2107,6 +2131,7 @@ static void calc_used_field_length(THD *thd, JOIN_TAB *join_tab)
join_tab
->
used_fields
=
fields
;
join_tab
->
used_fieldlength
=
rec_length
;
join_tab
->
used_blobs
=
blobs
;
DBUG_VOID_RETURN
;
}
...
...
@@ -2116,6 +2141,7 @@ cache_record_length(JOIN *join,uint idx)
uint
length
=
0
;
JOIN_TAB
**
pos
,
**
end
;
THD
*
thd
=
join
->
thd
;
DBUG_ENTER
(
"cache_record_length"
);
for
(
pos
=
join
->
best_ref
+
join
->
const_tables
,
end
=
join
->
best_ref
+
idx
;
pos
!=
end
;
...
...
@@ -2126,7 +2152,7 @@ cache_record_length(JOIN *join,uint idx)
calc_used_field_length
(
thd
,
join_tab
);
length
+=
join_tab
->
used_fieldlength
;
}
return
length
;
DBUG_RETURN
(
length
)
;
}
...
...
@@ -2134,6 +2160,7 @@ static double
prev_record_reads
(
JOIN
*
join
,
table_map
found_ref
)
{
double
found
=
1.0
;
DBUG_ENTER
(
"prev_record_reads"
);
for
(
POSITION
*
pos
=
join
->
positions
;
found_ref
;
pos
++
)
{
...
...
@@ -2143,7 +2170,7 @@ prev_record_reads(JOIN *join,table_map found_ref)
found
*=
pos
->
records_read
;
}
}
return
found
;
DBUG_RETURN
(
found
)
;
}
...
...
@@ -2160,11 +2187,12 @@ get_best_combination(JOIN *join)
KEYUSE
*
keyuse
;
uint
table_count
;
THD
*
thd
=
join
->
thd
;
DBUG_ENTER
(
"get_best_combination"
);
table_count
=
join
->
tables
;
if
(
!
(
join
->
join_tab
=
join_tab
=
(
JOIN_TAB
*
)
thd
->
alloc
(
sizeof
(
JOIN_TAB
)
*
table_count
)))
return
TRUE
;
DBUG_RETURN
(
TRUE
)
;
join
->
full_join
=
0
;
...
...
@@ -2193,13 +2221,13 @@ get_best_combination(JOIN *join)
join
->
full_join
=
1
;
}
else
if
(
create_ref_for_key
(
join
,
j
,
keyuse
,
used_tables
))
return
TRUE
;
// Something went wrong
DBUG_RETURN
(
TRUE
)
;
// Something went wrong
}
for
(
i
=
0
;
i
<
table_count
;
i
++
)
join
->
map2table
[
join
->
join_tab
[
i
].
table
->
tablenr
]
=
join
->
join_tab
+
i
;
update_depend_map
(
join
);
return
0
;
DBUG_RETURN
(
0
)
;
}
...
...
@@ -2212,6 +2240,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
uint
keyparts
,
length
,
key
;
TABLE
*
table
;
KEY
*
keyinfo
;
DBUG_ENTER
(
"create_ref_for_key"
);
/*
Use best key from find_best
...
...
@@ -2255,7 +2284,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
(
keyparts
+
1
))))
||
!
(
j
->
ref
.
items
=
(
Item
**
)
thd
->
alloc
(
sizeof
(
Item
*
)
*
keyparts
)))
{
return
TRUE
;
DBUG_RETURN
(
TRUE
)
;
}
j
->
ref
.
key_buff2
=
j
->
ref
.
key_buff
+
ALIGN_SIZE
(
length
);
j
->
ref
.
key_err
=
1
;
...
...
@@ -2267,7 +2296,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
{
j
->
ref
.
items
[
0
]
=
((
Item_func
*
)(
keyuse
->
val
))
->
key_item
();
if
(
keyuse
->
used_tables
)
return
TRUE
;
// not supported yet. SerG
DBUG_RETURN
(
TRUE
)
;
// not supported yet. SerG
j
->
type
=
JT_FT
;
}
...
...
@@ -2295,7 +2324,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
keyuse
->
val
);
if
(
thd
->
fatal_error
)
{
return
TRUE
;
DBUG_RETURN
(
TRUE
)
;
}
tmp
->
copy
();
}
...
...
@@ -2328,7 +2357,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
}
else
j
->
type
=
JT_EQ_REF
;
return
0
;
DBUG_RETURN
(
0
)
;
}
...
...
@@ -2337,29 +2366,31 @@ static store_key *
get_store_key
(
THD
*
thd
,
KEYUSE
*
keyuse
,
table_map
used_tables
,
KEY_PART_INFO
*
key_part
,
char
*
key_buff
,
uint
maybe_null
)
{
DBUG_ENTER
(
"get_store_key"
);
if
(
!
((
~
used_tables
)
&
keyuse
->
used_tables
))
// if const item
{
return
new
store_key_const_item
(
thd
,
DBUG_RETURN
(
new
store_key_const_item
(
thd
,
key_part
->
field
,
key_buff
+
maybe_null
,
maybe_null
?
key_buff
:
0
,
key_part
->
length
,
keyuse
->
val
);
keyuse
->
val
)
)
;
}
else
if
(
keyuse
->
val
->
type
()
==
Item
::
FIELD_ITEM
)
return
new
store_key_field
(
thd
,
DBUG_RETURN
(
new
store_key_field
(
thd
,
key_part
->
field
,
key_buff
+
maybe_null
,
maybe_null
?
key_buff
:
0
,
key_part
->
length
,
((
Item_field
*
)
keyuse
->
val
)
->
field
,
keyuse
->
val
->
full_name
());
return
new
store_key_item
(
thd
,
keyuse
->
val
->
full_name
())
)
;
DBUG_RETURN
(
new
store_key_item
(
thd
,
key_part
->
field
,
key_buff
+
maybe_null
,
maybe_null
?
key_buff
:
0
,
key_part
->
length
,
keyuse
->
val
);
keyuse
->
val
)
)
;
}
/*
...
...
@@ -2372,10 +2403,12 @@ store_val_in_field(Field *field,Item *item)
{
THD
*
thd
=
current_thd
;
ulong
cuted_fields
=
thd
->
cuted_fields
;
DBUG_ENTER
(
"store_val_in_field"
);
thd
->
count_cuted_fields
=
1
;
item
->
save_in_field
(
field
);
thd
->
count_cuted_fields
=
0
;
return
cuted_fields
!=
thd
->
cuted_fields
;
DBUG_RETURN
(
cuted_fields
!=
thd
->
cuted_fields
)
;
}
...
...
@@ -2384,10 +2417,11 @@ make_simple_join(JOIN *join,TABLE *tmp_table)
{
TABLE
**
tableptr
;
JOIN_TAB
*
join_tab
;
DBUG_ENTER
(
"make_simple_join"
);
if
(
!
(
tableptr
=
(
TABLE
**
)
join
->
thd
->
alloc
(
sizeof
(
TABLE
*
)))
||
!
(
join_tab
=
(
JOIN_TAB
*
)
join
->
thd
->
alloc
(
sizeof
(
JOIN_TAB
))))
return
TRUE
;
DBUG_RETURN
(
TRUE
)
;
join
->
join_tab
=
join_tab
;
join
->
table
=
tableptr
;
tableptr
[
0
]
=
tmp_table
;
join
->
tables
=
1
;
...
...
@@ -2419,7 +2453,7 @@ make_simple_join(JOIN *join,TABLE *tmp_table)
bzero
((
char
*
)
&
join_tab
->
read_record
,
sizeof
(
join_tab
->
read_record
));
tmp_table
->
status
=
0
;
tmp_table
->
null_row
=
0
;
return
FALSE
;
DBUG_RETURN
(
FALSE
)
;
}
...
...
@@ -2791,13 +2825,15 @@ join_free(JOIN *join)
static
bool
eq_ref_table
(
JOIN
*
join
,
ORDER
*
start_order
,
JOIN_TAB
*
tab
)
{
DBUG_ENTER
(
"eq_ref_table"
);
if
(
tab
->
cached_eq_ref_table
)
// If cached
return
tab
->
eq_ref_table
;
DBUG_RETURN
(
tab
->
eq_ref_table
)
;
tab
->
cached_eq_ref_table
=
1
;
if
(
tab
->
type
==
JT_CONST
)
// We can skip const tables
return
(
tab
->
eq_ref_table
=
1
);
/* purecov: inspected */
DBUG_RETURN
((
tab
->
eq_ref_table
=
1
)
);
/* purecov: inspected */
if
(
tab
->
type
!=
JT_EQ_REF
)
return
(
tab
->
eq_ref_table
=
0
);
// We must use this
DBUG_RETURN
((
tab
->
eq_ref_table
=
0
)
);
// We must use this
Item
**
ref_item
=
tab
->
ref
.
items
;
Item
**
end
=
ref_item
+
tab
->
ref
.
key_parts
;
uint
found
=
0
;
...
...
@@ -2821,7 +2857,7 @@ eq_ref_table(JOIN *join, ORDER *start_order, JOIN_TAB *tab)
continue
;
// Used in ORDER BY
}
if
(
!
only_eq_ref_tables
(
join
,
start_order
,
(
*
ref_item
)
->
used_tables
()))
return
(
tab
->
eq_ref_table
=
0
);
DBUG_RETURN
((
tab
->
eq_ref_table
=
0
)
);
}
}
/* Check that there was no reference to table before sort order */
...
...
@@ -2833,23 +2869,25 @@ eq_ref_table(JOIN *join, ORDER *start_order, JOIN_TAB *tab)
continue
;
}
if
(
start_order
->
depend_map
&
map
)
return
(
tab
->
eq_ref_table
=
0
);
DBUG_RETURN
((
tab
->
eq_ref_table
=
0
)
);
}
return
tab
->
eq_ref_table
=
1
;
DBUG_RETURN
(
tab
->
eq_ref_table
=
1
)
;
}
static
bool
only_eq_ref_tables
(
JOIN
*
join
,
ORDER
*
order
,
table_map
tables
)
{
DBUG_ENTER
(
"only_eq_ref_tables"
);
if
(
specialflag
&
SPECIAL_SAFE_MODE
)
return
0
;
// skip this optimize /* purecov: inspected */
DBUG_RETURN
(
0
)
;
// skip this optimize /* purecov: inspected */
for
(
JOIN_TAB
**
tab
=
join
->
map2table
;
tables
;
tab
++
,
tables
>>=
1
)
{
if
(
tables
&
1
&&
!
eq_ref_table
(
join
,
order
,
*
tab
))
return
0
;
DBUG_RETURN
(
0
)
;
}
return
1
;
DBUG_RETURN
(
1
)
;
}
...
...
@@ -2858,6 +2896,7 @@ only_eq_ref_tables(JOIN *join,ORDER *order,table_map tables)
static
void
update_depend_map
(
JOIN
*
join
)
{
JOIN_TAB
*
join_tab
=
join
->
join_tab
,
*
end
=
join_tab
+
join
->
tables
;
DBUG_ENTER
(
"update_depend_map"
);
for
(;
join_tab
!=
end
;
join_tab
++
)
{
...
...
@@ -2876,6 +2915,7 @@ static void update_depend_map(JOIN *join)
ref
->
depend_map
|=
(
*
tab
)
->
ref
.
depend_map
;
}
}
DBUG_VOID_RETURN
;
}
...
...
@@ -2883,6 +2923,8 @@ static void update_depend_map(JOIN *join)
static
void
update_depend_map
(
JOIN
*
join
,
ORDER
*
order
)
{
DBUG_ENTER
(
"update_depend_map"
);
for
(;
order
;
order
=
order
->
next
)
{
table_map
depend_map
;
...
...
@@ -2899,6 +2941,7 @@ static void update_depend_map(JOIN *join, ORDER *order)
}
}
}
DBUG_VOID_RETURN
;
}
...
...
@@ -2910,9 +2953,10 @@ static void update_depend_map(JOIN *join, ORDER *order)
static
ORDER
*
remove_const
(
JOIN
*
join
,
ORDER
*
first_order
,
COND
*
cond
,
bool
*
simple_order
)
{
if
(
join
->
tables
==
join
->
const_tables
)
return
0
;
// No need to sort
DBUG_ENTER
(
"remove_const"
);
if
(
join
->
tables
==
join
->
const_tables
)
DBUG_RETURN
(
0
);
// No need to sort
ORDER
*
order
,
**
prev_ptr
;
table_map
first_table
=
join
->
join_tab
[
join
->
const_tables
].
table
->
map
;
table_map
not_const_tables
=
~
join
->
const_table_map
;
...
...
@@ -3009,8 +3053,11 @@ return_zero_rows(JOIN *join, select_result *result,TABLE_LIST *tables,
static
void
clear_tables
(
JOIN
*
join
)
{
DBUG_ENTER
(
"clear_tables"
);
for
(
uint
i
=
0
;
i
<
join
->
tables
;
i
++
)
mark_as_null_row
(
join
->
table
[
i
]);
// All fields are NULL
DBUG_VOID_RETURN
;
}
/*****************************************************************************
...
...
@@ -3049,6 +3096,8 @@ static void
change_cond_ref_to_const
(
I_List
<
COND_CMP
>
*
save_list
,
Item
*
and_father
,
Item
*
cond
,
Item
*
field
,
Item
*
value
)
{
DBUG_ENTER
(
"change_cond_ref_to_const"
);
if
(
cond
->
type
()
==
Item
::
COND_ITEM
)
{
bool
and_level
=
((
Item_cond
*
)
cond
)
->
functype
()
==
...
...
@@ -3058,10 +3107,10 @@ change_cond_ref_to_const(I_List<COND_CMP> *save_list,Item *and_father,
while
((
item
=
li
++
))
change_cond_ref_to_const
(
save_list
,
and_level
?
cond
:
item
,
item
,
field
,
value
);
return
;
DBUG_VOID_RETURN
;
}
if
(
cond
->
eq_cmp_result
()
==
Item
::
COND_OK
)
return
;
// Not a boolean function
DBUG_VOID_RETURN
;
// Not a boolean function
Item_bool_func2
*
func
=
(
Item_bool_func2
*
)
cond
;
Item
*
left_item
=
func
->
arguments
()[
0
];
...
...
@@ -3108,6 +3157,7 @@ change_cond_ref_to_const(I_List<COND_CMP> *save_list,Item *and_father,
func
->
arguments
()[
1
]
->
result_type
()));
}
}
DBUG_VOID_RETURN
;
}
...
...
@@ -3115,6 +3165,8 @@ static void
propagate_cond_constants
(
I_List
<
COND_CMP
>
*
save_list
,
COND
*
and_level
,
COND
*
cond
)
{
DBUG_ENTER
(
"propagate_cond_constants"
);
if
(
cond
->
type
()
==
Item
::
COND_ITEM
)
{
bool
and_level
=
((
Item_cond
*
)
cond
)
->
functype
()
==
...
...
@@ -3172,16 +3224,19 @@ propagate_cond_constants(I_List<COND_CMP> *save_list,COND *and_level,
}
}
}
DBUG_VOID_RETURN
;
}
static
COND
*
optimize_cond
(
COND
*
conds
,
Item
::
cond_result
*
cond_value
)
{
DBUG_ENTER
(
"optimize_cond"
);
if
(
!
conds
)
{
*
cond_value
=
Item
::
COND_TRUE
;
return
conds
;
DBUG_RETURN
(
conds
)
;
}
/* change field = field to field = const for each found field = const */
DBUG_EXECUTE
(
"where"
,
print_where
(
conds
,
"original"
););
...
...
@@ -3193,7 +3248,7 @@ optimize_cond(COND *conds,Item::cond_result *cond_value)
DBUG_EXECUTE
(
"where"
,
print_where
(
conds
,
"after const change"
););
conds
=
remove_eq_conds
(
conds
,
cond_value
)
;
DBUG_EXECUTE
(
"info"
,
print_where
(
conds
,
"after remove"
););
return
conds
;
DBUG_RETURN
(
conds
)
;
}
...
...
@@ -3208,6 +3263,8 @@ optimize_cond(COND *conds,Item::cond_result *cond_value)
static
COND
*
remove_eq_conds
(
COND
*
cond
,
Item
::
cond_result
*
cond_value
)
{
DBUG_ENTER
(
"remove_eq_conds"
);
if
(
cond
->
type
()
==
Item
::
COND_ITEM
)
{
bool
and_level
=
((
Item_cond
*
)
cond
)
->
functype
()
...
...
@@ -3245,14 +3302,14 @@ remove_eq_conds(COND *cond,Item::cond_result *cond_value)
if
(
and_level
)
{
*
cond_value
=
tmp_cond_value
;
return
(
COND
*
)
0
;
// Always false
DBUG_RETURN
((
COND
*
)
0
)
;
// Always false
}
break
;
case
Item
:
:
COND_TRUE
:
if
(
!
and_level
)
{
*
cond_value
=
tmp_cond_value
;
return
(
COND
*
)
0
;
// Always true
DBUG_RETURN
((
COND
*
)
0
)
;
// Always true
}
break
;
case
Item
:
:
COND_UNDEF
:
// Impossible
...
...
@@ -3261,12 +3318,12 @@ remove_eq_conds(COND *cond,Item::cond_result *cond_value)
}
if
(
!
((
Item_cond
*
)
cond
)
->
argument_list
()
->
elements
||
*
cond_value
!=
Item
::
COND_OK
)
return
(
COND
*
)
0
;
DBUG_RETURN
((
COND
*
)
0
)
;
if
(((
Item_cond
*
)
cond
)
->
argument_list
()
->
elements
==
1
)
{
// Remove list
item
=
((
Item_cond
*
)
cond
)
->
argument_list
()
->
head
();
((
Item_cond
*
)
cond
)
->
argument_list
()
->
empty
();
return
item
;
DBUG_RETURN
(
item
)
;
}
}
else
if
(
cond
->
type
()
==
Item
::
FUNC_ITEM
&&
...
...
@@ -3322,7 +3379,7 @@ remove_eq_conds(COND *cond,Item::cond_result *cond_value)
else
if
(
cond
->
const_item
())
{
*
cond_value
=
eval_const_cond
(
cond
)
?
Item
::
COND_TRUE
:
Item
::
COND_FALSE
;
return
(
COND
*
)
0
;
DBUG_RETURN
((
COND
*
)
0
)
;
}
else
if
((
*
cond_value
=
cond
->
eq_cmp_result
())
!=
Item
::
COND_OK
)
{
// boolan compare function
...
...
@@ -3332,11 +3389,11 @@ remove_eq_conds(COND *cond,Item::cond_result *cond_value)
{
if
(
!
left_item
->
maybe_null
||
((
Item_func
*
)
cond
)
->
functype
()
==
Item_func
::
EQUAL_FUNC
)
return
(
COND
*
)
0
;
// Compare of identical items
DBUG_RETURN
((
COND
*
)
0
)
;
// Compare of identical items
}
}
*
cond_value
=
Item
::
COND_OK
;
return
cond
;
// Point at next and level
DBUG_RETURN
(
cond
)
;
// Point at next and level
}
/*
...
...
@@ -3346,6 +3403,8 @@ remove_eq_conds(COND *cond,Item::cond_result *cond_value)
static
bool
const_expression_in_where
(
COND
*
cond
,
Item
*
comp_item
,
Item
**
const_item
)
{
DBUG_ENTER
(
"const_expression_in_where"
);
if
(
cond
->
type
()
==
Item
::
COND_ITEM
)
{
bool
and_level
=
(((
Item_cond
*
)
cond
)
->
functype
()
...
...
@@ -3358,19 +3417,19 @@ const_expression_in_where(COND *cond, Item *comp_item, Item **const_item)
if
(
res
)
// Is a const value
{
if
(
and_level
)
return
1
;
DBUG_RETURN
(
1
)
;
}
else
if
(
!
and_level
)
return
0
;
DBUG_RETURN
(
0
)
;
}
return
and_level
?
0
:
1
;
DBUG_RETURN
(
and_level
?
0
:
1
)
;
}
else
if
(
cond
->
eq_cmp_result
()
!=
Item
::
COND_OK
)
{
// boolan compare function
Item_func
*
func
=
(
Item_func
*
)
cond
;
if
(
func
->
functype
()
!=
Item_func
::
EQUAL_FUNC
&&
func
->
functype
()
!=
Item_func
::
EQ_FUNC
)
return
0
;
DBUG_RETURN
(
0
)
;
Item
*
left_item
=
((
Item_func
*
)
cond
)
->
arguments
()[
0
];
Item
*
right_item
=
((
Item_func
*
)
cond
)
->
arguments
()[
1
];
if
(
left_item
->
eq
(
comp_item
,
1
))
...
...
@@ -3378,9 +3437,9 @@ const_expression_in_where(COND *cond, Item *comp_item, Item **const_item)
if
(
right_item
->
const_item
())
{
if
(
*
const_item
)
return
right_item
->
eq
(
*
const_item
,
1
);
DBUG_RETURN
(
right_item
->
eq
(
*
const_item
,
1
)
);
*
const_item
=
right_item
;
return
1
;
DBUG_RETURN
(
1
)
;
}
}
else
if
(
right_item
->
eq
(
comp_item
,
1
))
...
...
@@ -3388,13 +3447,13 @@ const_expression_in_where(COND *cond, Item *comp_item, Item **const_item)
if
(
left_item
->
const_item
())
{
if
(
*
const_item
)
return
left_item
->
eq
(
*
const_item
,
1
);
DBUG_RETURN
(
left_item
->
eq
(
*
const_item
,
1
)
);
*
const_item
=
left_item
;
return
1
;
DBUG_RETURN
(
1
)
;
}
}
}
return
0
;
DBUG_RETURN
(
0
)
;
}
...
...
@@ -3409,6 +3468,8 @@ 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
)
{
DBUG_ENTER
(
"*create_tmp_field"
);
switch
(
type
)
{
case
Item
:
:
SUM_FUNC_ITEM
:
{
...
...
@@ -3417,38 +3478,46 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
switch
(
item_sum
->
sum_func
())
{
case
Item_sum
:
:
AVG_FUNC
:
/* Place for sum & count */
if
(
group
)
return
new
Field_string
(
sizeof
(
double
)
+
sizeof
(
longlong
),
maybe_null
,
item
->
name
,
table
,
1
);
{
DBUG_RETURN
(
new
Field_string
(
sizeof
(
double
)
+
sizeof
(
longlong
),
maybe_null
,
item
->
name
,
table
,
1
));
}
else
return
new
Field_double
(
item_sum
->
max_length
,
maybe_null
,
item
->
name
,
table
,
item_sum
->
decimals
);
{
DBUG_RETURN
(
new
Field_double
(
item_sum
->
max_length
,
maybe_null
,
item
->
name
,
table
,
item_sum
->
decimals
));
}
case
Item_sum
:
:
STD_FUNC
:
/* Place for sum & count */
if
(
group
)
return
new
Field_string
(
sizeof
(
double
)
*
2
+
sizeof
(
longlong
),
maybe_null
,
item
->
name
,
table
,
1
);
{
DBUG_RETURN
(
new
Field_string
(
sizeof
(
double
)
*
2
+
sizeof
(
longlong
),
maybe_null
,
item
->
name
,
table
,
1
));
}
else
return
new
Field_double
(
item_sum
->
max_length
,
maybe_null
,
item
->
name
,
table
,
item_sum
->
decimals
);
{
DBUG_RETURN
(
new
Field_double
(
item_sum
->
max_length
,
maybe_null
,
item
->
name
,
table
,
item_sum
->
decimals
));
}
case
Item_sum
:
:
UNIQUE_USERS_FUNC
:
return
new
Field_long
(
9
,
maybe_null
,
item
->
name
,
table
,
1
);
DBUG_RETURN
(
new
Field_long
(
9
,
maybe_null
,
item
->
name
,
table
,
1
)
);
default:
switch
(
item_sum
->
result_type
())
{
case
REAL_RESULT
:
return
new
Field_double
(
item_sum
->
max_length
,
maybe_null
,
item
->
name
,
table
,
item_sum
->
decimals
);
DBUG_RETURN
(
new
Field_double
(
item_sum
->
max_length
,
maybe_null
,
item
->
name
,
table
,
item_sum
->
decimals
)
)
;
case
INT_RESULT
:
return
new
Field_longlong
(
item_sum
->
max_length
,
maybe_null
,
item
->
name
,
table
,
item
->
unsigned_flag
);
DBUG_RETURN
(
new
Field_longlong
(
item_sum
->
max_length
,
maybe_null
,
item
->
name
,
table
,
item
->
unsigned_flag
)
)
;
case
STRING_RESULT
:
if
(
item_sum
->
max_length
>
255
)
return
new
Field_blob
(
item_sum
->
max_length
,
maybe_null
,
item
->
name
,
table
,
item
->
binary
);
return
new
Field_string
(
item_sum
->
max_length
,
maybe_null
,
item
->
name
,
table
,
item
->
binary
);
DBUG_RETURN
(
new
Field_blob
(
item_sum
->
max_length
,
maybe_null
,
item
->
name
,
table
,
item
->
binary
)
)
;
DBUG_RETURN
(
new
Field_string
(
item_sum
->
max_length
,
maybe_null
,
item
->
name
,
table
,
item
->
binary
)
)
;
}
}
thd
->
fatal_error
=
1
;
return
0
;
// Error
DBUG_RETURN
(
0
)
;
// Error
}
case
Item
:
:
FIELD_ITEM
:
{
...
...
@@ -3465,7 +3534,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
if
(
org_field
->
maybe_null
())
new_field
->
flags
&=
~
NOT_NULL_FLAG
;
// Because of outer join
}
return
new_field
;
DBUG_RETURN
(
new_field
)
;
}
case
Item
:
:
PROC_ITEM
:
case
Item
:
:
FUNC_ITEM
:
...
...
@@ -3505,11 +3574,12 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
*
((
*
copy_func
)
++
)
=
(
Item_result_field
*
)
item
;
// Save for copy_funcs
if
(
modify_item
)
((
Item_result_field
*
)
item
)
->
result_field
=
new_field
;
return
new_field
;
DBUG_RETURN
(
new_field
)
;
}
default:
// Dosen't have to be stored
return
0
;
DBUG_RETURN
(
0
)
;
}
DBUG_RETURN
(
0
);
// impossible
}
...
...
@@ -3534,8 +3604,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
Item_result_field
**
copy_func
;
MI_COLUMNDEF
*
recinfo
;
uint
temp_pool_slot
=
MY_BIT_NONE
;
DBUG_ENTER
(
"create_tmp_table"
);
DBUG_PRINT
(
"enter"
,(
"distinct: %d save_sum_fields: %d allow_distinct_limit: %d group: %d"
,
(
int
)
distinct
,
(
int
)
save_sum_fields
,
(
int
)
allow_distinct_limit
,
test
(
group
)));
...
...
@@ -3983,15 +4053,17 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
static
bool
open_tmp_table
(
TABLE
*
table
)
{
int
error
;
DBUG_ENTER
(
"open_tmp_table"
);
if
((
error
=
table
->
file
->
ha_open
(
table
->
real_name
,
O_RDWR
,
HA_OPEN_TMP_TABLE
)))
{
table
->
file
->
print_error
(
error
,
MYF
(
0
));
/* purecov: inspected */
table
->
db_stat
=
0
;
return
(
1
);
DBUG_RETURN
((
1
)
);
}
/* VOID(ha_lock(table,F_WRLCK)); */
/* Single thread table */
(
void
)
table
->
file
->
extra
(
HA_EXTRA_QUICK
);
/* Faster */
return
(
0
);
DBUG_RETURN
((
0
)
);
}
...
...
@@ -4002,8 +4074,8 @@ static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
MI_KEYDEF
keydef
;
MI_UNIQUEDEF
uniquedef
;
KEY
*
keyinfo
=
param
->
keyinfo
;
DBUG_ENTER
(
"create_myisam_tmp_table"
);
if
(
table
->
keys
)
{
// Get keys for ni_create
bool
using_unique_constraint
=
0
;
...
...
@@ -4340,37 +4412,39 @@ static int
sub_select_cache
(
JOIN
*
join
,
JOIN_TAB
*
join_tab
,
bool
end_of_records
)
{
int
error
;
DBUG_ENTER
(
"sub_select_cache"
);
if
(
end_of_records
)
{
if
((
error
=
flush_cached_records
(
join
,
join_tab
,
FALSE
))
<
0
)
return
error
;
/* purecov: inspected */
return
sub_select
(
join
,
join_tab
,
end_of_records
);
DBUG_RETURN
(
error
)
;
/* purecov: inspected */
DBUG_RETURN
(
sub_select
(
join
,
join_tab
,
end_of_records
)
);
}
if
(
join
->
thd
->
killed
)
// If aborted by user
{
my_error
(
ER_SERVER_SHUTDOWN
,
MYF
(
0
));
/* purecov: inspected */
return
-
2
;
/* purecov: inspected */
DBUG_RETURN
(
-
2
)
;
/* purecov: inspected */
}
if
(
join_tab
->
use_quick
!=
2
||
test_if_quick_select
(
join_tab
)
<=
0
)
{
if
(
!
store_record_in_cache
(
&
join_tab
->
cache
))
return
0
;
// There is more room in cache
return
flush_cached_records
(
join
,
join_tab
,
FALSE
);
DBUG_RETURN
(
0
)
;
// There is more room in cache
DBUG_RETURN
(
flush_cached_records
(
join
,
join_tab
,
FALSE
)
);
}
if
((
error
=
flush_cached_records
(
join
,
join_tab
,
TRUE
))
<
0
)
return
error
;
/* purecov: inspected */
return
sub_select
(
join
,
join_tab
,
end_of_records
);
/* Use ordinary select */
DBUG_RETURN
(
error
)
;
/* purecov: inspected */
DBUG_RETURN
(
sub_select
(
join
,
join_tab
,
end_of_records
)
);
/* Use ordinary select */
}
static
int
sub_select
(
JOIN
*
join
,
JOIN_TAB
*
join_tab
,
bool
end_of_records
)
{
DBUG_ENTER
(
"sub_select"
);
join_tab
->
table
->
null_row
=
0
;
if
(
end_of_records
)
return
(
*
join_tab
->
next_select
)(
join
,
join_tab
+
1
,
end_of_records
);
DBUG_RETURN
((
*
join_tab
->
next_select
)(
join
,
join_tab
+
1
,
end_of_records
)
);
/* Cache variables for faster loop */
int
error
;
...
...
@@ -4389,7 +4463,7 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
if
(
join
->
thd
->
killed
)
// Aborted by user
{
my_error
(
ER_SERVER_SHUTDOWN
,
MYF
(
0
));
/* purecov: inspected */
return
-
2
;
/* purecov: inspected */
DBUG_RETURN
(
-
2
)
;
/* purecov: inspected */
}
join
->
examined_rows
++
;
if
(
!
on_expr
||
on_expr
->
val_int
())
...
...
@@ -4400,9 +4474,9 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
if
(
!
select_cond
||
select_cond
->
val_int
())
{
if
((
error
=
(
*
join_tab
->
next_select
)(
join
,
join_tab
+
1
,
0
))
<
0
)
return
error
;
DBUG_RETURN
(
error
)
;
if
(
not_used_in_distinct
&&
found_records
!=
join
->
found_records
)
return
0
;
DBUG_RETURN
(
0
)
;
}
else
info
->
file
->
unlock_row
();
...
...
@@ -4410,7 +4484,7 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
}
while
(
!
(
error
=
info
->
read_record
(
info
)));
}
if
(
error
>
0
)
// Fatal error
return
-
1
;
DBUG_RETURN
(
-
1
)
;
if
(
!
found
&&
on_expr
)
{
// OUTER JOIN
...
...
@@ -4419,10 +4493,10 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
if
(
!
select_cond
||
select_cond
->
val_int
())
{
if
((
error
=
(
*
join_tab
->
next_select
)(
join
,
join_tab
+
1
,
0
))
<
0
)
return
error
;
/* purecov: inspected */
DBUG_RETURN
(
error
)
;
/* purecov: inspected */
}
}
return
0
;
DBUG_RETURN
(
0
)
;
}
...
...
@@ -4431,9 +4505,10 @@ flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skipp_last)
{
int
error
;
READ_RECORD
*
info
;
DBUG_ENTER
(
"flush_cached_records"
);
if
(
!
join_tab
->
cache
.
records
)
return
0
;
/* Nothing to do */
DBUG_RETURN
(
0
)
;
/* Nothing to do */
if
(
skipp_last
)
(
void
)
store_record_in_cache
(
&
join_tab
->
cache
);
// Must save this for later
if
(
join_tab
->
use_quick
==
2
)
...
...
@@ -4449,7 +4524,7 @@ flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skipp_last)
{
reset_cache
(
&
join_tab
->
cache
);
join_tab
->
cache
.
records
=
0
;
join_tab
->
cache
.
ptr_record
=
(
uint
)
~
0
;
return
-
error
;
/* No records or error */
DBUG_RETURN
(
-
error
)
;
/* No records or error */
}
for
(
JOIN_TAB
*
tmp
=
join
->
join_tab
;
tmp
!=
join_tab
;
tmp
++
)
...
...
@@ -4464,7 +4539,7 @@ flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skipp_last)
if
(
join
->
thd
->
killed
)
{
my_error
(
ER_SERVER_SHUTDOWN
,
MYF
(
0
));
/* purecov: inspected */
return
-
2
;
// Aborted by user /* purecov: inspected */
DBUG_RETURN
(
-
2
)
;
// Aborted by user /* purecov: inspected */
}
SQL_SELECT
*
select
=
join_tab
->
select
;
if
(
!
error
&&
(
!
join_tab
->
cache
.
select
||
...
...
@@ -4477,7 +4552,7 @@ flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skipp_last)
read_cached_record
(
join_tab
);
if
(
!
select
||
!
select
->
skipp_record
())
if
((
error
=
(
join_tab
->
next_select
)(
join
,
join_tab
+
1
,
0
))
<
0
)
return
error
;
/* purecov: inspected */
DBUG_RETURN
(
error
)
;
/* purecov: inspected */
}
}
}
while
(
!
(
error
=
info
->
read_record
(
info
)));
...
...
@@ -4487,10 +4562,10 @@ flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skipp_last)
reset_cache
(
&
join_tab
->
cache
);
join_tab
->
cache
.
records
=
0
;
join_tab
->
cache
.
ptr_record
=
(
uint
)
~
0
;
if
(
error
>
0
)
// Fatal error
return
-
1
;
/* purecov: inspected */
DBUG_RETURN
(
-
1
)
;
/* purecov: inspected */
for
(
JOIN_TAB
*
tmp2
=
join
->
join_tab
;
tmp2
!=
join_tab
;
tmp2
++
)
tmp2
->
table
->
status
=
tmp2
->
status
;
return
0
;
DBUG_RETURN
(
0
)
;
}
...
...
@@ -4546,6 +4621,8 @@ join_read_system(JOIN_TAB *tab)
{
TABLE
*
table
=
tab
->
table
;
int
error
;
DBUG_ENTER
(
"join_read_system"
);
if
(
table
->
status
&
STATUS_GARBAGE
)
// If first read
{
if
((
error
=
table
->
file
->
read_first_row
(
table
->
record
[
0
],
...
...
@@ -4554,18 +4631,18 @@ join_read_system(JOIN_TAB *tab)
if
(
error
!=
HA_ERR_END_OF_FILE
)
{
table
->
file
->
print_error
(
error
,
MYF
(
0
));
return
1
;
DBUG_RETURN
(
1
)
;
}
table
->
null_row
=
1
;
// This is ok.
empty_record
(
table
);
// Make empty record
return
-
1
;
DBUG_RETURN
(
-
1
)
;
}
store_record
(
table
,
1
);
}
else
if
(
!
table
->
status
)
// Only happens with left join
restore_record
(
table
,
1
);
// restore old record
table
->
null_row
=
0
;
return
table
->
status
?
-
1
:
0
;
DBUG_RETURN
(
table
->
status
?
-
1
:
0
)
;
}
...
...
@@ -4574,6 +4651,8 @@ join_read_const(JOIN_TAB *tab)
{
int
error
;
TABLE
*
table
=
tab
->
table
;
DBUG_ENTER
(
"join_read_const"
);
if
(
table
->
status
&
STATUS_GARBAGE
)
// If first read
{
if
(
cp_buffer_from_ref
(
&
tab
->
ref
))
...
...
@@ -4593,9 +4672,9 @@ join_read_const(JOIN_TAB *tab)
sql_print_error
(
"read_const: Got error %d when reading table %s"
,
error
,
table
->
path
);
table
->
file
->
print_error
(
error
,
MYF
(
0
));
return
1
;
DBUG_RETURN
(
1
)
;
}
return
-
1
;
DBUG_RETURN
(
-
1
)
;
}
store_record
(
table
,
1
);
}
...
...
@@ -4605,7 +4684,7 @@ join_read_const(JOIN_TAB *tab)
restore_record
(
table
,
1
);
// restore old record
}
table
->
null_row
=
0
;
return
table
->
status
?
-
1
:
0
;
DBUG_RETURN
(
table
->
status
?
-
1
:
0
)
;
}
...
...
@@ -4614,6 +4693,7 @@ join_read_key(JOIN_TAB *tab)
{
int
error
;
TABLE
*
table
=
tab
->
table
;
DBUG_ENTER
(
"join_read_key"
);
if
(
cmp_buffer_with_ref
(
tab
)
||
(
table
->
status
&
(
STATUS_GARBAGE
|
STATUS_NO_PARENT
|
STATUS_NULL_ROW
)))
...
...
@@ -4621,7 +4701,7 @@ join_read_key(JOIN_TAB *tab)
if
(
tab
->
ref
.
key_err
)
{
table
->
status
=
STATUS_NOT_FOUND
;
return
-
1
;
DBUG_RETURN
(
-
1
)
;
}
error
=
table
->
file
->
index_read
(
table
->
record
[
0
],
tab
->
ref
.
key_buff
,
...
...
@@ -4631,11 +4711,11 @@ join_read_key(JOIN_TAB *tab)
sql_print_error
(
"read_key: Got error %d when reading table '%s'"
,
error
,
table
->
path
);
table
->
file
->
print_error
(
error
,
MYF
(
0
));
return
1
;
DBUG_RETURN
(
1
)
;
}
}
table
->
null_row
=
0
;
return
table
->
status
?
-
1
:
0
;
DBUG_RETURN
(
table
->
status
?
-
1
:
0
)
;
}
...
...
@@ -4644,9 +4724,10 @@ join_read_always_key(JOIN_TAB *tab)
{
int
error
;
TABLE
*
table
=
tab
->
table
;
DBUG_ENTER
(
"join_read_always_key"
);
if
(
cp_buffer_from_ref
(
&
tab
->
ref
))
return
-
1
;
DBUG_RETURN
(
-
1
)
;
if
((
error
=
table
->
file
->
index_read
(
table
->
record
[
0
],
tab
->
ref
.
key_buff
,
tab
->
ref
.
key_length
,
HA_READ_KEY_EXACT
)))
...
...
@@ -4656,11 +4737,11 @@ join_read_always_key(JOIN_TAB *tab)
sql_print_error
(
"read_const: Got error %d when reading table %s"
,
error
,
table
->
path
);
table
->
file
->
print_error
(
error
,
MYF
(
0
));
return
1
;
DBUG_RETURN
(
1
)
;
}
return
-
1
;
/* purecov: inspected */
DBUG_RETURN
(
-
1
)
;
/* purecov: inspected */
}
return
0
;
DBUG_RETURN
(
0
)
;
}
/*
...
...
@@ -4673,9 +4754,10 @@ join_read_last_key(JOIN_TAB *tab)
{
int
error
;
TABLE
*
table
=
tab
->
table
;
DBUG_ENTER
(
"join_read_last_key"
);
if
(
cp_buffer_from_ref
(
&
tab
->
ref
))
return
-
1
;
DBUG_RETURN
(
-
1
)
;
if
((
error
=
table
->
file
->
index_read_last
(
table
->
record
[
0
],
tab
->
ref
.
key_buff
,
tab
->
ref
.
key_length
)))
...
...
@@ -4685,11 +4767,11 @@ join_read_last_key(JOIN_TAB *tab)
sql_print_error
(
"read_const: Got error %d when reading table %s"
,
error
,
table
->
path
);
table
->
file
->
print_error
(
error
,
MYF
(
0
));
return
1
;
DBUG_RETURN
(
1
)
;
}
return
-
1
;
/* purecov: inspected */
DBUG_RETURN
(
-
1
)
;
/* purecov: inspected */
}
return
0
;
DBUG_RETURN
(
0
)
;
}
...
...
@@ -4697,7 +4779,8 @@ join_read_last_key(JOIN_TAB *tab)
static
int
join_no_more_records
(
READ_RECORD
*
info
__attribute__
((
unused
)))
{
return
-
1
;
DBUG_ENTER
(
"join_no_more_records"
);
DBUG_RETURN
(
-
1
);
}
...
...
@@ -4707,6 +4790,7 @@ join_read_next_same(READ_RECORD *info)
int
error
;
TABLE
*
table
=
info
->
table
;
JOIN_TAB
*
tab
=
table
->
reginfo
.
join_tab
;
DBUG_ENTER
(
"join_read_next_same"
);
if
((
error
=
table
->
file
->
index_next_same
(
table
->
record
[
0
],
tab
->
ref
.
key_buff
,
...
...
@@ -4717,12 +4801,12 @@ join_read_next_same(READ_RECORD *info)
sql_print_error
(
"read_next: Got error %d when reading table %s"
,
error
,
table
->
path
);
table
->
file
->
print_error
(
error
,
MYF
(
0
));
return
1
;
DBUG_RETURN
(
1
)
;
}
table
->
status
=
STATUS_GARBAGE
;
return
-
1
;
DBUG_RETURN
(
-
1
)
;
}
return
0
;
DBUG_RETURN
(
0
)
;
}
static
int
...
...
@@ -4731,6 +4815,7 @@ join_read_prev_same(READ_RECORD *info)
int
error
;
TABLE
*
table
=
info
->
table
;
JOIN_TAB
*
tab
=
table
->
reginfo
.
join_tab
;
DBUG_ENTER
(
"join_read_prev_same"
);
if
((
error
=
table
->
file
->
index_prev
(
table
->
record
[
0
])))
{
...
...
@@ -4753,16 +4838,18 @@ join_read_prev_same(READ_RECORD *info)
table
->
status
=
STATUS_NOT_FOUND
;
error
=
-
1
;
}
return
error
;
DBUG_RETURN
(
error
)
;
}
static
int
join_init_quick_read_record
(
JOIN_TAB
*
tab
)
{
DBUG_ENTER
(
"join_init_quick_read_record"
);
if
(
test_if_quick_select
(
tab
)
==
-
1
)
return
-
1
;
/* No possible records */
return
join_init_read_record
(
tab
);
DBUG_RETURN
(
-
1
)
;
/* No possible records */
DBUG_RETURN
(
join_init_read_record
(
tab
)
);
}
...
...
@@ -4770,19 +4857,23 @@ static int
test_if_quick_select
(
JOIN_TAB
*
tab
)
{
delete
tab
->
select
->
quick
;
DBUG_ENTER
(
"test_if_quick_select"
);
tab
->
select
->
quick
=
0
;
return
tab
->
select
->
test_quick_select
(
tab
->
keys
,(
table_map
)
0
,
HA_POS_ERROR
);
DBUG_RETURN
(
tab
->
select
->
test_quick_select
(
tab
->
keys
,(
table_map
)
0
,
HA_POS_ERROR
)
);
}
static
int
join_init_read_record
(
JOIN_TAB
*
tab
)
{
DBUG_ENTER
(
"join_init_read_record"
);
if
(
tab
->
select
&&
tab
->
select
->
quick
)
tab
->
select
->
quick
->
reset
();
init_read_record
(
&
tab
->
read_record
,
tab
->
join
->
thd
,
tab
->
table
,
tab
->
select
,
1
,
1
);
return
(
*
tab
->
read_record
.
read_record
)(
&
tab
->
read_record
);
DBUG_RETURN
((
*
tab
->
read_record
.
read_record
)(
&
tab
->
read_record
)
);
}
static
int
...
...
@@ -4790,6 +4881,8 @@ join_read_first(JOIN_TAB *tab)
{
int
error
;
TABLE
*
table
=
tab
->
table
;
DBUG_ENTER
(
"join_read_first"
);
if
(
!
table
->
key_read
&&
(
table
->
used_keys
&
((
key_map
)
1
<<
tab
->
index
))
&&
!
table
->
no_keyread
)
{
...
...
@@ -4810,11 +4903,11 @@ join_read_first(JOIN_TAB *tab)
sql_print_error
(
"read_first_with_key: Got error %d when reading table"
,
error
);
table
->
file
->
print_error
(
error
,
MYF
(
0
));
return
1
;
DBUG_RETURN
(
1
)
;
}
return
-
1
;
DBUG_RETURN
(
-
1
)
;
}
return
0
;
DBUG_RETURN
(
0
)
;
}
...
...
@@ -4822,6 +4915,8 @@ static int
join_read_next
(
READ_RECORD
*
info
)
{
int
error
=
info
->
file
->
index_next
(
info
->
record
);
DBUG_ENTER
(
"join_read_next"
);
if
(
error
)
{
if
(
error
!=
HA_ERR_END_OF_FILE
)
...
...
@@ -4829,11 +4924,11 @@ join_read_next(READ_RECORD *info)
sql_print_error
(
"read_next_with_key: Got error %d when reading table %s"
,
error
,
info
->
table
->
path
);
info
->
file
->
print_error
(
error
,
MYF
(
0
));
return
1
;
DBUG_RETURN
(
1
)
;
}
return
-
1
;
DBUG_RETURN
(
-
1
)
;
}
return
0
;
DBUG_RETURN
(
0
)
;
}
static
int
...
...
@@ -4841,6 +4936,8 @@ join_read_last(JOIN_TAB *tab)
{
TABLE
*
table
=
tab
->
table
;
int
error
;
DBUG_ENTER
(
"join_read_last"
);
if
(
!
table
->
key_read
&&
(
table
->
used_keys
&
((
key_map
)
1
<<
tab
->
index
))
&&
!
table
->
no_keyread
)
{
...
...
@@ -4861,11 +4958,11 @@ join_read_last(JOIN_TAB *tab)
sql_print_error
(
"read_last_with_key: Got error %d when reading table"
,
error
,
table
->
path
);
table
->
file
->
print_error
(
error
,
MYF
(
0
));
return
1
;
DBUG_RETURN
(
1
)
;
}
return
-
1
;
DBUG_RETURN
(
-
1
)
;
}
return
0
;
DBUG_RETURN
(
0
)
;
}
...
...
@@ -4873,6 +4970,8 @@ static int
join_read_prev
(
READ_RECORD
*
info
)
{
int
error
=
info
->
file
->
index_prev
(
info
->
record
);
DBUG_ENTER
(
"join_read_prev"
);
if
(
error
)
{
if
(
error
!=
HA_ERR_END_OF_FILE
)
...
...
@@ -4880,11 +4979,11 @@ join_read_prev(READ_RECORD *info)
sql_print_error
(
"read_prev_with_key: Got error %d when reading table: %s"
,
error
,
info
->
table
->
path
);
info
->
file
->
print_error
(
error
,
MYF
(
0
));
return
1
;
DBUG_RETURN
(
1
)
;
}
return
-
1
;
DBUG_RETURN
(
-
1
)
;
}
return
0
;
DBUG_RETURN
(
0
)
;
}
...
...
@@ -4893,10 +4992,11 @@ join_ft_read_first(JOIN_TAB *tab)
{
int
error
;
TABLE
*
table
=
tab
->
table
;
DBUG_ENTER
(
"join_ft_read_first"
);
#if NOT_USED_YET
if
(
cp_buffer_from_ref
(
&
tab
->
ref
))
// as ft-key doesn't use store_key's
return
-
1
;
// see also FT_SELECT::init()
DBUG_RETURN
(
-
1
)
;
// see also FT_SELECT::init()
#endif
table
->
file
->
ft_init
();
...
...
@@ -4908,17 +5008,19 @@ join_ft_read_first(JOIN_TAB *tab)
sql_print_error
(
"ft_read_first: Got error %d when reading table %s"
,
error
,
table
->
path
);
table
->
file
->
print_error
(
error
,
MYF
(
0
));
return
1
;
DBUG_RETURN
(
1
)
;
}
return
-
1
;
DBUG_RETURN
(
-
1
)
;
}
return
0
;
DBUG_RETURN
(
0
)
;
}
static
int
join_ft_read_next
(
READ_RECORD
*
info
)
{
int
error
=
info
->
file
->
ft_read
(
info
->
table
->
record
[
0
]);
DBUG_ENTER
(
"join_ft_read_next"
);
if
(
error
)
{
if
(
error
!=
HA_ERR_END_OF_FILE
)
...
...
@@ -4926,11 +5028,11 @@ join_ft_read_next(READ_RECORD *info)
sql_print_error
(
"ft_read_next: Got error %d when reading table %s"
,
error
,
info
->
table
->
path
);
info
->
file
->
print_error
(
error
,
MYF
(
0
));
return
1
;
DBUG_RETURN
(
1
)
;
}
return
-
1
;
DBUG_RETURN
(
-
1
)
;
}
return
0
;
DBUG_RETURN
(
0
)
;
}
...
...
@@ -5347,6 +5449,8 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
static
bool
test_if_ref
(
Item_field
*
left_item
,
Item
*
right_item
)
{
Field
*
field
=
left_item
->
field
;
DBUG_ENTER
(
"test_if_ref"
);
// No need to change const test. We also have to keep tests on LEFT JOIN
if
(
!
field
->
table
->
const_table
&&
!
field
->
table
->
maybe_null
)
{
...
...
@@ -5354,7 +5458,7 @@ static bool test_if_ref(Item_field *left_item,Item *right_item)
if
(
ref_item
&&
ref_item
->
eq
(
right_item
,
1
))
{
if
(
right_item
->
type
()
==
Item
::
FIELD_ITEM
)
return
(
field
->
eq_def
(((
Item_field
*
)
right_item
)
->
field
));
DBUG_RETURN
((
field
->
eq_def
(((
Item_field
*
)
right_item
)
->
field
)
));
if
(
right_item
->
const_item
()
&&
!
(
right_item
->
is_null
()))
{
/*
...
...
@@ -5364,27 +5468,29 @@ static bool test_if_ref(Item_field *left_item,Item *right_item)
if
(
field
->
binary
()
&&
(
field
->
type
()
!=
FIELD_TYPE_FLOAT
||
field
->
decimals
()
==
0
))
{
return
!
store_val_in_field
(
field
,
right_item
);
DBUG_RETURN
(
!
store_val_in_field
(
field
,
right_item
)
);
}
}
}
}
return
0
;
// keep test
DBUG_RETURN
(
0
)
;
// keep test
}
static
COND
*
make_cond_for_table
(
COND
*
cond
,
table_map
tables
,
table_map
used_table
)
{
DBUG_ENTER
(
"make_cond_for_table"
);
if
(
used_table
&&
!
(
cond
->
used_tables
()
&
used_table
))
return
(
COND
*
)
0
;
// Already checked
DBUG_RETURN
((
COND
*
)
0
)
;
// Already checked
if
(
cond
->
type
()
==
Item
::
COND_ITEM
)
{
if
(((
Item_cond
*
)
cond
)
->
functype
()
==
Item_func
::
COND_AND_FUNC
)
{
Item_cond_and
*
new_cond
=
new
Item_cond_and
;
if
(
!
new_cond
)
return
(
COND
*
)
0
;
// OOM /* purecov: inspected */
DBUG_RETURN
((
COND
*
)
0
)
;
// OOM /* purecov: inspected */
List_iterator
<
Item
>
li
(
*
((
Item_cond
*
)
cond
)
->
argument_list
());
Item
*
item
;
while
((
item
=
li
++
))
...
...
@@ -5395,31 +5501,31 @@ make_cond_for_table(COND *cond,table_map tables,table_map used_table)
}
switch
(
new_cond
->
argument_list
()
->
elements
)
{
case
0
:
return
(
COND
*
)
0
;
// Always true
DBUG_RETURN
((
COND
*
)
0
)
;
// Always true
case
1
:
return
new_cond
->
argument_list
()
->
head
(
);
DBUG_RETURN
(
new_cond
->
argument_list
()
->
head
()
);
default:
new_cond
->
used_tables_cache
=
((
Item_cond
*
)
cond
)
->
used_tables_cache
&
tables
;
return
new_cond
;
DBUG_RETURN
(
new_cond
)
;
}
}
else
{
// Or list
Item_cond_or
*
new_cond
=
new
Item_cond_or
;
if
(
!
new_cond
)
return
(
COND
*
)
0
;
// OOM /* purecov: inspected */
DBUG_RETURN
((
COND
*
)
0
)
;
// OOM /* purecov: inspected */
List_iterator
<
Item
>
li
(
*
((
Item_cond
*
)
cond
)
->
argument_list
());
Item
*
item
;
while
((
item
=
li
++
))
{
Item
*
fix
=
make_cond_for_table
(
item
,
tables
,
0L
);
if
(
!
fix
)
return
(
COND
*
)
0
;
// Always true
DBUG_RETURN
((
COND
*
)
0
)
;
// Always true
new_cond
->
argument_list
()
->
push_back
(
fix
);
}
new_cond
->
used_tables_cache
=
((
Item_cond_or
*
)
cond
)
->
used_tables_cache
;
return
new_cond
;
DBUG_RETURN
(
new_cond
)
;
}
}
...
...
@@ -5430,9 +5536,9 @@ make_cond_for_table(COND *cond,table_map tables,table_map used_table)
*/
if
(
cond
->
marker
==
3
||
(
cond
->
used_tables
()
&
~
tables
))
return
(
COND
*
)
0
;
// Can't check this yet
DBUG_RETURN
((
COND
*
)
0
)
;
// Can't check this yet
if
(
cond
->
marker
==
2
||
cond
->
eq_cmp_result
()
==
Item
::
COND_OK
)
return
cond
;
// Not boolean op
DBUG_RETURN
(
cond
)
;
// Not boolean op
if
(((
Item_func
*
)
cond
)
->
functype
()
==
Item_func
::
EQ_FUNC
)
{
...
...
@@ -5442,23 +5548,25 @@ make_cond_for_table(COND *cond,table_map tables,table_map used_table)
test_if_ref
((
Item_field
*
)
left_item
,
right_item
))
{
cond
->
marker
=
3
;
// Checked when read
return
(
COND
*
)
0
;
DBUG_RETURN
((
COND
*
)
0
)
;
}
if
(
right_item
->
type
()
==
Item
::
FIELD_ITEM
&&
test_if_ref
((
Item_field
*
)
right_item
,
left_item
))
{
cond
->
marker
=
3
;
// Checked when read
return
(
COND
*
)
0
;
DBUG_RETURN
((
COND
*
)
0
)
;
}
}
cond
->
marker
=
2
;
return
cond
;
DBUG_RETURN
(
cond
)
;
}
static
Item
*
part_of_refkey
(
TABLE
*
table
,
Field
*
field
)
{
uint
ref_parts
=
table
->
reginfo
.
join_tab
->
ref
.
key_parts
;
DBUG_ENTER
(
"part_of_refkey"
);
if
(
ref_parts
)
{
KEY_PART_INFO
*
key_part
=
...
...
@@ -5467,9 +5575,9 @@ part_of_refkey(TABLE *table,Field *field)
for
(
uint
part
=
0
;
part
<
ref_parts
;
part
++
,
key_part
++
)
if
(
field
->
eq
(
key_part
->
field
)
&&
!
(
key_part
->
key_part_flag
&
HA_PART_KEY
))
return
table
->
reginfo
.
join_tab
->
ref
.
items
[
part
]
;
DBUG_RETURN
(
table
->
reginfo
.
join_tab
->
ref
.
items
[
part
])
;
}
return
(
Item
*
)
0
;
DBUG_RETURN
((
Item
*
)
0
)
;
}
...
...
@@ -5485,6 +5593,8 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx,
uint
*
used_key_parts
)
{
KEY_PART_INFO
*
key_part
,
*
key_part_end
;
DBUG_ENTER
(
"test_if_order_by_key"
);
key_part
=
table
->
key_info
[
idx
].
key_part
;
key_part_end
=
key_part
+
table
->
key_info
[
idx
].
key_parts
;
key_part_map
const_key_parts
=
table
->
const_key_parts
[
idx
];
...
...
@@ -5504,24 +5614,26 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx,
key_part
++
;
const_key_parts
>>=
1
;
}
if
(
key_part
==
key_part_end
||
key_part
->
field
!=
field
)
return
0
;
DBUG_RETURN
(
0
)
;
/* set flag to 1 if we can use read-next on key, else to -1 */
flag
=
(
order
->
asc
==
!
(
key_part
->
key_part_flag
&
HA_REVERSE_SORT
))
?
1
:
-
1
;
if
(
reverse
&&
flag
!=
reverse
)
return
0
;
DBUG_RETURN
(
0
)
;
reverse
=
flag
;
// Remember if reverse
key_part
++
;
}
*
used_key_parts
=
(
uint
)
(
key_part
-
table
->
key_info
[
idx
].
key_part
);
return
reverse
;
DBUG_RETURN
(
reverse
)
;
}
static
uint
find_shortest_key
(
TABLE
*
table
,
key_map
usable_keys
)
{
uint
min_length
=
(
uint
)
~
0
;
uint
best
=
MAX_KEY
;
DBUG_ENTER
(
"find_shortest_key"
);
for
(
uint
nr
=
0
;
usable_keys
;
usable_keys
>>=
1
,
nr
++
)
{
if
(
usable_keys
&
1
)
...
...
@@ -5533,7 +5645,7 @@ static uint find_shortest_key(TABLE *table, key_map usable_keys)
}
}
}
return
best
;
DBUG_RETURN
(
best
)
;
}
...
...
@@ -5752,6 +5864,8 @@ err:
#ifdef NOT_YET
static
bool
fix_having
(
JOIN
*
join
,
Item
**
having
)
{
DBUG_ENTER
(
"fix_having"
);
(
*
having
)
->
update_used_tables
();
// Some tables may have been const
JOIN_TAB
*
table
=&
join
->
join_tab
[
join
->
const_tables
];
table_map
used_tables
=
join
->
const_table_map
|
table
->
table
->
map
;
...
...
@@ -5762,20 +5876,20 @@ static bool fix_having(JOIN *join, Item **having)
{
if
(
!
table
->
select
)
if
(
!
(
table
->
select
=
new
SQL_SELECT
))
return
1
;
DBUG_RETURN
(
1
)
;
if
(
!
table
->
select
->
cond
)
table
->
select
->
cond
=
sort_table_cond
;
else
// This should never happen
if
(
!
(
table
->
select
->
cond
=
new
Item_cond_and
(
table
->
select
->
cond
,
sort_table_cond
)))
return
1
;
DBUG_RETURN
(
1
)
;
table
->
select_cond
=
table
->
select
->
cond
;
DBUG_EXECUTE
(
"where"
,
print_where
(
table
->
select_cond
,
"select and having"
););
*
having
=
make_cond_for_table
(
*
having
,
~
(
table_map
)
0
,
~
used_tables
);
DBUG_EXECUTE
(
"where"
,
print_where
(
*
having
,
"having after make_cond"
););
}
return
0
;
DBUG_RETURN
(
0
)
;
}
#endif
...
...
@@ -5790,32 +5904,39 @@ static bool fix_having(JOIN *join, Item **having)
static
bool
compare_record
(
TABLE
*
table
,
Field
**
ptr
)
{
DBUG_ENTER
(
"compare_record"
);
for
(;
*
ptr
;
ptr
++
)
{
if
((
*
ptr
)
->
cmp_offset
(
table
->
rec_buff_length
))
return
1
;
DBUG_RETURN
(
1
)
;
}
return
0
;
DBUG_RETURN
(
0
)
;
}
static
bool
copy_blobs
(
Field
**
ptr
)
{
DBUG_ENTER
(
"copy_blobs"
);
for
(;
*
ptr
;
ptr
++
)
{
if
((
*
ptr
)
->
flags
&
BLOB_FLAG
)
if
(((
Field_blob
*
)
(
*
ptr
))
->
copy
())
return
1
;
// Error
DBUG_RETURN
(
1
)
;
// Error
}
return
0
;
DBUG_RETURN
(
0
)
;
}
static
void
free_blobs
(
Field
**
ptr
)
{
DBUG_ENTER
(
"free_blobs"
);
for
(;
*
ptr
;
ptr
++
)
{
if
((
*
ptr
)
->
flags
&
BLOB_FLAG
)
((
Field_blob
*
)
(
*
ptr
))
->
free
();
}
DBUG_VOID_RETURN
;
}
...
...
@@ -6062,7 +6183,7 @@ SORT_FIELD *make_unireg_sortorder(ORDER *order, uint *length)
count
++
;
pos
=
sort
=
(
SORT_FIELD
*
)
sql_alloc
(
sizeof
(
SORT_FIELD
)
*
(
count
+
1
));
if
(
!
pos
)
return
0
;
DBUG_RETURN
(
0
)
;
for
(;
order
;
order
=
order
->
next
,
pos
++
)
{
...
...
@@ -6188,13 +6309,15 @@ static ulong
used_blob_length
(
CACHE_FIELD
**
ptr
)
{
uint
length
,
blob_length
;
DBUG_ENTER
(
"used_blob_length"
);
for
(
length
=
0
;
*
ptr
;
ptr
++
)
{
(
*
ptr
)
->
blob_length
=
blob_length
=
(
*
ptr
)
->
blob_field
->
get_length
();
length
+=
blob_length
;
(
*
ptr
)
->
blob_field
->
get_ptr
(
&
(
*
ptr
)
->
str
);
}
return
length
;
DBUG_RETURN
(
length
)
;
}
...
...
@@ -6205,6 +6328,7 @@ store_record_in_cache(JOIN_CACHE *cache)
uchar
*
pos
;
CACHE_FIELD
*
copy
,
*
end_field
;
bool
last_record
;
DBUG_ENTER
(
"store_record_in_cache"
);
pos
=
cache
->
pos
;
end_field
=
cache
->
field
+
cache
->
fields
;
...
...
@@ -6256,15 +6380,18 @@ store_record_in_cache(JOIN_CACHE *cache)
}
}
cache
->
pos
=
pos
;
return
last_record
||
(
uint
)
(
cache
->
end
-
pos
)
<
cache
->
length
;
DBUG_RETURN
(
last_record
||
(
uint
)
(
cache
->
end
-
pos
)
<
cache
->
length
)
;
}
static
void
reset_cache
(
JOIN_CACHE
*
cache
)
{
DBUG_ENTER
(
"reset_cache"
);
cache
->
record_nr
=
0
;
cache
->
pos
=
cache
->
buff
;
DBUG_VOID_RETURN
;
}
...
...
@@ -6275,6 +6402,7 @@ read_cached_record(JOIN_TAB *tab)
uint
length
;
bool
last_record
;
CACHE_FIELD
*
copy
,
*
end_field
;
DBUG_ENTER
(
"read_cached_record"
);
last_record
=
tab
->
cache
.
record_nr
++
==
tab
->
cache
.
ptr_record
;
pos
=
tab
->
cache
.
pos
;
...
...
@@ -6312,7 +6440,7 @@ read_cached_record(JOIN_TAB *tab)
}
}
tab
->
cache
.
pos
=
pos
;
return
;
DBUG_VOID_RETURN
;
}
...
...
@@ -6320,24 +6448,28 @@ static bool
cmp_buffer_with_ref
(
JOIN_TAB
*
tab
)
{
bool
diff
;
DBUG_ENTER
(
"cmp_buffer_with_ref"
);
if
(
!
(
diff
=
tab
->
ref
.
key_err
))
{
memcpy
(
tab
->
ref
.
key_buff2
,
tab
->
ref
.
key_buff
,
tab
->
ref
.
key_length
);
}
if
((
tab
->
ref
.
key_err
=
cp_buffer_from_ref
(
&
tab
->
ref
))
||
diff
)
return
1
;
return
memcmp
(
tab
->
ref
.
key_buff2
,
tab
->
ref
.
key_buff
,
tab
->
ref
.
key_length
)
!=
0
;
DBUG_RETURN
(
1
)
;
DBUG_RETURN
(
memcmp
(
tab
->
ref
.
key_buff2
,
tab
->
ref
.
key_buff
,
tab
->
ref
.
key_length
)
!=
0
)
;
}
bool
cp_buffer_from_ref
(
TABLE_REF
*
ref
)
{
DBUG_ENTER
(
"cp_buffer_from_ref"
);
for
(
store_key
**
copy
=
ref
->
key_copy
;
*
copy
;
copy
++
)
if
((
*
copy
)
->
copy
())
return
1
;
// Something went wrong
return
0
;
DBUG_RETURN
(
1
)
;
// Something went wrong
DBUG_RETURN
(
0
)
;
}
...
...
@@ -6355,6 +6487,8 @@ static int
find_order_in_list
(
THD
*
thd
,
TABLE_LIST
*
tables
,
ORDER
*
order
,
List
<
Item
>
&
fields
,
List
<
Item
>
&
all_fields
)
{
DBUG_ENTER
(
"find_order_in_list"
);
if
((
*
order
->
item
)
->
type
()
==
Item
::
INT_ITEM
)
{
/* Order by position */
Item
*
item
=
0
;
...
...
@@ -6367,11 +6501,11 @@ find_order_in_list(THD *thd,TABLE_LIST *tables,ORDER *order,List<Item> &fields,
my_printf_error
(
ER_BAD_FIELD_ERROR
,
ER
(
ER_BAD_FIELD_ERROR
),
MYF
(
0
),(
*
order
->
item
)
->
full_name
(),
thd
->
where
);
return
1
;
DBUG_RETURN
(
1
)
;
}
order
->
item
=
li
.
ref
();
order
->
in_field_list
=
1
;
return
0
;
DBUG_RETURN
(
0
)
;
}
const
char
*
save_where
=
thd
->
where
;
thd
->
where
=
0
;
// No error if not found
...
...
@@ -6381,14 +6515,14 @@ find_order_in_list(THD *thd,TABLE_LIST *tables,ORDER *order,List<Item> &fields,
{
order
->
item
=
item
;
// use it
order
->
in_field_list
=
1
;
return
0
;
DBUG_RETURN
(
0
)
;
}
order
->
in_field_list
=
0
;
if
((
*
order
->
item
)
->
fix_fields
(
thd
,
tables
)
||
thd
->
fatal_error
)
return
1
;
// Wrong field
DBUG_RETURN
(
1
)
;
// Wrong field
all_fields
.
push_front
(
*
order
->
item
);
// Add new field to field list
order
->
item
=
(
Item
**
)
all_fields
.
head_ref
();
return
0
;
DBUG_RETURN
(
0
)
;
}
...
...
@@ -6400,13 +6534,15 @@ find_order_in_list(THD *thd,TABLE_LIST *tables,ORDER *order,List<Item> &fields,
int
setup_order
(
THD
*
thd
,
TABLE_LIST
*
tables
,
List
<
Item
>
&
fields
,
List
<
Item
>
&
all_fields
,
ORDER
*
order
)
{
DBUG_ENTER
(
"setup_order"
);
thd
->
where
=
"order clause"
;
for
(;
order
;
order
=
order
->
next
)
{
if
(
find_order_in_list
(
thd
,
tables
,
order
,
fields
,
all_fields
))
return
1
;
DBUG_RETURN
(
1
)
;
}
return
0
;
DBUG_RETURN
(
0
)
;
}
...
...
@@ -6414,9 +6550,11 @@ static int
setup_group
(
THD
*
thd
,
TABLE_LIST
*
tables
,
List
<
Item
>
&
fields
,
List
<
Item
>
&
all_fields
,
ORDER
*
order
,
bool
*
hidden_group_fields
)
{
DBUG_ENTER
(
"setup_group"
);
*
hidden_group_fields
=
0
;
if
(
!
order
)
return
0
;
/* Everything is ok */
DBUG_RETURN
(
0
)
;
/* Everything is ok */
if
(
thd
->
sql_mode
&
MODE_ONLY_FULL_GROUP_BY
)
{
...
...
@@ -6431,13 +6569,13 @@ setup_group(THD *thd,TABLE_LIST *tables,List<Item> &fields,
for
(;
order
;
order
=
order
->
next
)
{
if
(
find_order_in_list
(
thd
,
tables
,
order
,
fields
,
all_fields
))
return
1
;
DBUG_RETURN
(
1
)
;
(
*
order
->
item
)
->
marker
=
1
;
/* Mark found */
if
((
*
order
->
item
)
->
with_sum_func
)
{
my_printf_error
(
ER_WRONG_GROUP_FIELD
,
ER
(
ER_WRONG_GROUP_FIELD
),
MYF
(
0
),
(
*
order
->
item
)
->
full_name
());
return
1
;
DBUG_RETURN
(
1
)
;
}
}
if
(
thd
->
sql_mode
&
MODE_ONLY_FULL_GROUP_BY
)
...
...
@@ -6453,13 +6591,13 @@ setup_group(THD *thd,TABLE_LIST *tables,List<Item> &fields,
my_printf_error
(
ER_WRONG_FIELD_WITH_GROUP
,
ER
(
ER_WRONG_FIELD_WITH_GROUP
),
MYF
(
0
),
item
->
full_name
());
return
1
;
DBUG_RETURN
(
1
)
;
}
}
}
if
(
org_fields
!=
all_fields
.
elements
)
*
hidden_group_fields
=
1
;
// group fields is not used
return
0
;
DBUG_RETURN
(
0
)
;
}
/*
...
...
@@ -6504,6 +6642,7 @@ create_distinct_group(ORDER *order_list,List<Item> &fields)
List_iterator
<
Item
>
li
(
fields
);
Item
*
item
;
ORDER
*
order
,
*
group
,
**
prev
;
DBUG_ENTER
(
"create_distinct_group"
);
while
((
item
=
li
++
))
item
->
marker
=
0
;
/* Marker that field is not used */
...
...
@@ -6515,7 +6654,7 @@ create_distinct_group(ORDER *order_list,List<Item> &fields)
{
ORDER
*
ord
=
(
ORDER
*
)
sql_memdup
(
order
,
sizeof
(
ORDER
));
if
(
!
ord
)
return
0
;
DBUG_RETURN
(
0
)
;
*
prev
=
ord
;
prev
=
&
ord
->
next
;
(
*
ord
->
item
)
->
marker
=
1
;
...
...
@@ -6531,7 +6670,7 @@ create_distinct_group(ORDER *order_list,List<Item> &fields)
{
ORDER
*
ord
=
(
ORDER
*
)
sql_calloc
(
sizeof
(
ORDER
));
if
(
!
ord
)
return
0
;
DBUG_RETURN
(
0
)
;
ord
->
item
=
li
.
ref
();
ord
->
asc
=
1
;
*
prev
=
ord
;
...
...
@@ -6539,7 +6678,7 @@ create_distinct_group(ORDER *order_list,List<Item> &fields)
}
}
*
prev
=
0
;
return
group
;
DBUG_RETURN
(
group
)
;
}
...
...
@@ -6553,6 +6692,7 @@ count_field_types(TMP_TABLE_PARAM *param, List<Item> &fields,
{
List_iterator
<
Item
>
li
(
fields
);
Item
*
field
;
DBUG_ENTER
(
"count_field_types"
);
param
->
field_count
=
param
->
sum_func_count
=
param
->
func_count
=
param
->
hidden_field_count
=
0
;
...
...
@@ -6587,6 +6727,7 @@ count_field_types(TMP_TABLE_PARAM *param, List<Item> &fields,
field
->
with_sum_func
=
0
;
}
}
DBUG_VOID_RETURN
;
}
...
...
@@ -6599,14 +6740,16 @@ count_field_types(TMP_TABLE_PARAM *param, List<Item> &fields,
static
bool
test_if_subpart
(
ORDER
*
a
,
ORDER
*
b
)
{
DBUG_ENTER
(
"test_if_subpart"
);
for
(;
a
&&
b
;
a
=
a
->
next
,
b
=
b
->
next
)
{
if
((
*
a
->
item
)
->
eq
(
*
b
->
item
,
1
))
a
->
asc
=
b
->
asc
;
else
return
0
;
DBUG_RETURN
(
0
)
;
}
return
test
(
!
b
);
DBUG_RETURN
(
test
(
!
b
)
);
}
/*
...
...
@@ -6649,6 +6792,7 @@ static void
calc_group_buffer
(
JOIN
*
join
,
ORDER
*
group
)
{
uint
key_length
=
0
,
parts
=
0
,
null_parts
=
0
;
DBUG_ENTER
(
"calc_group_buffer"
);
if
(
group
)
join
->
group
=
1
;
...
...
@@ -6675,6 +6819,7 @@ calc_group_buffer(JOIN *join,ORDER *group)
join
->
tmp_table_param
.
group_length
=
key_length
+
null_parts
;
join
->
tmp_table_param
.
group_parts
=
parts
;
join
->
tmp_table_param
.
group_null_parts
=
null_parts
;
DBUG_VOID_RETURN
;
}
...
...
@@ -6686,17 +6831,19 @@ calc_group_buffer(JOIN *join,ORDER *group)
static
bool
alloc_group_fields
(
JOIN
*
join
,
ORDER
*
group
)
{
DBUG_ENTER
(
"alloc_group_fields"
);
if
(
group
)
{
for
(;
group
;
group
=
group
->
next
)
{
Item_buff
*
tmp
=
new_Item_buff
(
*
group
->
item
);
if
(
!
tmp
||
join
->
group_fields
.
push_front
(
tmp
))
return
TRUE
;
DBUG_RETURN
(
TRUE
)
;
}
}
join
->
sort_and_group
=
1
;
/* Mark for do_select */
return
FALSE
;
DBUG_RETURN
(
FALSE
)
;
}
...
...
@@ -6706,13 +6853,14 @@ test_if_group_changed(List<Item_buff> &list)
List_iterator
<
Item_buff
>
li
(
list
);
int
idx
=
-
1
,
i
;
Item_buff
*
buff
;
DBUG_ENTER
(
"test_if_group_changed"
);
for
(
i
=
(
int
)
list
.
elements
-
1
;
(
buff
=
li
++
)
;
i
--
)
{
if
(
buff
->
cmp
())
idx
=
i
;
}
return
idx
;
DBUG_RETURN
(
idx
)
;
}
...
...
@@ -6798,6 +6946,7 @@ copy_fields(TMP_TABLE_PARAM *param)
{
Copy_field
*
ptr
=
param
->
copy_field
;
Copy_field
*
end
=
param
->
copy_field_end
;
DBUG_ENTER
(
"copy_fields"
);
for
(;
ptr
!=
end
;
ptr
++
)
(
*
ptr
->
do_copy
)(
ptr
);
...
...
@@ -6807,6 +6956,7 @@ copy_fields(TMP_TABLE_PARAM *param)
Item_copy_string
*
item
;
while
((
item
=
(
Item_copy_string
*
)
it
++
))
item
->
copy
();
DBUG_VOID_RETURN
;
}
...
...
@@ -6851,6 +7001,7 @@ change_to_use_tmp_fields(List<Item> &items)
{
List_iterator
<
Item
>
it
(
items
);
Item
*
item_field
,
*
item
;
DBUG_ENTER
(
"change_to_use_tmp_fields"
);
while
((
item
=
it
++
))
{
...
...
@@ -6869,7 +7020,7 @@ change_to_use_tmp_fields(List<Item> &items)
else
item_field
=
(
Item
*
)
new
Item_field
(
field
);
if
(
!
item_field
)
return
TRUE
;
// Fatal error
DBUG_RETURN
(
TRUE
)
;
// Fatal error
item_field
->
name
=
item
->
name
;
/*lint -e613 */
#ifndef DBUG_OFF
if
(
_db_on_
&&
!
item_field
->
name
)
...
...
@@ -6888,7 +7039,7 @@ change_to_use_tmp_fields(List<Item> &items)
#endif
}
}
return
FALSE
;
DBUG_RETURN
(
FALSE
)
;
}
...
...
@@ -6902,6 +7053,7 @@ change_refs_to_tmp_fields(THD *thd,List<Item> &items)
{
List_iterator
<
Item
>
it
(
items
);
Item
*
item
;
DBUG_ENTER
(
"change_refs_to_tmp_fields"
);
while
((
item
=
it
++
))
{
...
...
@@ -6944,7 +7096,7 @@ change_refs_to_tmp_fields(THD *thd,List<Item> &items)
((
Item_field
*
)
item
)
->
field
=
((
Item_field
*
)
item
)
->
result_field
;
}
}
return
thd
->
fatal_error
;
DBUG_RETURN
(
thd
->
fatal_error
)
;
}
...
...
@@ -6957,8 +7109,11 @@ static void
init_tmptable_sum_functions
(
Item_sum
**
func_ptr
)
{
Item_sum
*
func
;
DBUG_ENTER
(
"init_tmptable_sum_functions"
);
while
((
func
=
*
(
func_ptr
++
)))
func
->
reset_field
();
DBUG_VOID_RETURN
;
}
...
...
@@ -6969,8 +7124,11 @@ update_tmptable_sum_func(Item_sum **func_ptr,
TABLE
*
tmp_table
__attribute__
((
unused
)))
{
Item_sum
*
func
;
DBUG_ENTER
(
"update_tmptable_sum_func"
);
while
((
func
=
*
(
func_ptr
++
)))
func
->
update_field
(
0
);
DBUG_VOID_RETURN
;
}
...
...
@@ -6980,9 +7138,11 @@ static void
copy_sum_funcs
(
Item_sum
**
func_ptr
)
{
Item_sum
*
func
;
DBUG_ENTER
(
"copy_sum_funcs"
);
for
(;
(
func
=
*
func_ptr
)
;
func_ptr
++
)
(
void
)
func
->
save_in_field
(
func
->
result_field
);
return
;
DBUG_VOID_RETURN
;
}
...
...
@@ -6990,8 +7150,11 @@ static void
init_sum_functions
(
Item_sum
**
func_ptr
)
{
Item_sum
*
func
;
DBUG_ENTER
(
"init_sum_functions"
);
for
(;
(
func
=
(
Item_sum
*
)
*
func_ptr
)
;
func_ptr
++
)
func
->
reset
();
DBUG_VOID_RETURN
;
}
...
...
@@ -6999,10 +7162,12 @@ static bool
update_sum_func
(
Item_sum
**
func_ptr
)
{
Item_sum
*
func
;
DBUG_ENTER
(
"update_sum_func"
);
for
(;
(
func
=
(
Item_sum
*
)
*
func_ptr
)
;
func_ptr
++
)
if
(
func
->
add
())
return
1
;
return
0
;
DBUG_RETURN
(
1
)
;
DBUG_RETURN
(
0
)
;
}
/* Copy result of functions to record in tmp_table */
...
...
@@ -7011,9 +7176,11 @@ void
copy_funcs
(
Item_result_field
**
func_ptr
)
{
Item_result_field
*
func
;
DBUG_ENTER
(
"copy_funcs"
);
for
(;
(
func
=
*
func_ptr
)
;
func_ptr
++
)
(
void
)
func
->
save_in_field
(
func
->
result_field
);
return
;
DBUG_VOID_RETURN
;
}
...
...
@@ -7096,7 +7263,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
field_list
.
push_back
(
new
Item_real
(
"rows"
,
0.0
,
0
,
10
));
field_list
.
push_back
(
new
Item_empty_string
(
"Extra"
,
255
));
if
(
result
->
send_fields
(
field_list
,
1
))
return
;
DBUG_VOID_RETURN
;
}
if
(
message
)
...
...
@@ -7239,11 +7406,12 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
static
void
describe_info
(
JOIN
*
join
,
const
char
*
info
)
{
THD
*
thd
=
join
->
thd
;
DBUG_ENTER
(
"describe_info"
);
if
(
thd
->
lex
.
select_lex
.
next
)
/* If in UNION */
{
select_describe
(
join
,
FALSE
,
FALSE
,
FALSE
,
info
);
return
;
DBUG_VOID_RETURN
;
}
List
<
Item
>
field_list
;
String
*
packet
=
&
thd
->
packet
;
...
...
@@ -7253,9 +7421,10 @@ static void describe_info(JOIN *join, const char *info)
QUERY_NO_GOOD_INDEX_USED
);
field_list
.
push_back
(
new
Item_empty_string
(
"Comment"
,
80
));
if
(
send_fields
(
thd
,
field_list
,
1
))
return
;
/* purecov: inspected */
DBUG_VOID_RETURN
;
/* purecov: inspected */
packet
->
length
(
0
);
net_store_data
(
packet
,
info
);
if
(
!
my_net_write
(
&
thd
->
net
,(
char
*
)
packet
->
ptr
(),
packet
->
length
()))
send_eof
(
&
thd
->
net
);
DBUG_VOID_RETURN
;
}
sql/stacktrace.c
View file @
cd6bf73f
...
...
@@ -206,7 +206,7 @@ resolve it\n");
/* Produce a core for the thread */
#ifdef
HAVE_LINUXTHREADS
#ifdef
NOT_USED
/* HAVE_LINUXTHREADS */
void
write_core
(
int
sig
)
{
signal
(
sig
,
SIG_DFL
);
...
...
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