Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
MariaDB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
df298ac6
Commit
df298ac6
authored
Jun 28, 2001
by
tim@white.box
Browse files
Options
Browse Files
Download
Plain Diff
Merge work:/home/bk/mysql-4.0 into white.box:/home/tim/my/4
parents
51e3c5de
5ed2cf7d
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
262 additions
and
5 deletions
+262
-5
.bzrignore
.bzrignore
+2
-0
BitKeeper/etc/logging_ok
BitKeeper/etc/logging_ok
+1
-0
mysql-test/mysql-test-run.sh
mysql-test/mysql-test-run.sh
+1
-1
mysql-test/r/order_by.result
mysql-test/r/order_by.result
+56
-0
mysql-test/t/order_by.test
mysql-test/t/order_by.test
+22
-0
sql/opt_range.cc
sql/opt_range.cc
+155
-3
sql/opt_range.h
sql/opt_range.h
+14
-0
sql/sql_select.cc
sql/sql_select.cc
+11
-1
No files found.
.bzrignore
View file @
df298ac6
...
@@ -368,3 +368,5 @@ libmysqld/hash_filo.cc
...
@@ -368,3 +368,5 @@ libmysqld/hash_filo.cc
libmysqld/sql_unions.cc
libmysqld/sql_unions.cc
libmysqld/stacktrace.c
libmysqld/stacktrace.c
sql/share/mysql
sql/share/mysql
.gdbinit
.vimrc
BitKeeper/etc/logging_ok
View file @
df298ac6
...
@@ -20,3 +20,4 @@ tim@threads.polyesthetic.msg
...
@@ -20,3 +20,4 @@ tim@threads.polyesthetic.msg
tim@work.mysql.com
tim@work.mysql.com
tonu@hundin.mysql.fi
tonu@hundin.mysql.fi
tonu@x3.internalnet
tonu@x3.internalnet
tim@white.box
mysql-test/mysql-test-run.sh
View file @
df298ac6
...
@@ -251,7 +251,7 @@ fi
...
@@ -251,7 +251,7 @@ fi
[
-z
"
$COLUMNS
"
]
&&
COLUMNS
=
80
[
-z
"
$COLUMNS
"
]
&&
COLUMNS
=
80
E
=
`
$EXPR
$COLUMNS
- 8
`
E
=
`
$EXPR
$COLUMNS
- 8
`
#DASH72=`
expr
substr '------------------------------------------------------------------------' 1 $E`
#DASH72=`
$EXPR
substr '------------------------------------------------------------------------' 1 $E`
DASH72
=
`
$ECHO
'------------------------------------------------------------------------'
|
$CUT
-c
1-
$E
`
DASH72
=
`
$ECHO
'------------------------------------------------------------------------'
|
$CUT
-c
1-
$E
`
# on source dist, we pick up freshly build executables
# on source dist, we pick up freshly build executables
...
...
mysql-test/r/order_by.result
View file @
df298ac6
...
@@ -111,3 +111,59 @@ DateOfAction TransactionID
...
@@ -111,3 +111,59 @@ DateOfAction TransactionID
member_id nickname voornaam
member_id nickname voornaam
1
1
2
2
table type possible_keys key key_len ref rows Extra
t1 index NULL a 20 NULL 10 Using index
a b c
1 NULL NULL
1 NULL b
1 1 NULL
1 1 b
1 1 b
2 0 a
2 0 b
2 1 a
2 1 b
2 1 c
table type possible_keys key key_len ref rows Extra
t1 index NULL a 20 NULL 10 Using index
a b c
2 1 c
2 1 b
2 1 a
2 0 b
2 0 a
1 1 b
1 1 b
1 1 NULL
1 NULL b
1 NULL NULL
table type possible_keys key key_len ref rows Extra
t1 range a a 20 NULL 2 where used; Using index
a b c
1 1 b
1 1 b
table type possible_keys key key_len ref rows Extra
t1 range a a 4 NULL 5 where used; Using index
a b c
1 1 b
1 1 b
1 1 NULL
table type possible_keys key key_len ref rows Extra
t1 range a a 9 NULL 7 where used; Using index
a b c
2 1 c
2 1 b
2 1 a
2 0 b
2 0 a
1 1 b
1 1 b
1 1 NULL
table type possible_keys key key_len ref rows Extra
t1 range a a 4 NULL 4 where used; Using index
a b c
1 1 b
1 1 b
1 1 NULL
1 NULL b
1 NULL NULL
mysql-test/t/order_by.test
View file @
df298ac6
...
@@ -205,3 +205,25 @@ select member_id, nickname, voornaam FROM members
...
@@ -205,3 +205,25 @@ select member_id, nickname, voornaam FROM members
ORDER
by
lastchange_datum
DESC
LIMIT
2
;
ORDER
by
lastchange_datum
DESC
LIMIT
2
;
drop
table
members
;
drop
table
members
;
create
table
t1
(
a
int
not
null
,
b
int
,
c
varchar
(
10
),
key
(
a
,
b
,
c
));
insert
into
t1
values
(
1
,
NULL
,
NULL
),
(
1
,
NULL
,
'b'
),
(
1
,
1
,
NULL
),
(
1
,
1
,
'b'
),
(
1
,
1
,
'b'
),
(
2
,
0
,
'a'
),
(
2
,
0
,
'b'
),
(
2
,
1
,
'a'
),
(
2
,
1
,
'b'
),
(
2
,
1
,
'c'
);
explain
select
*
from
t1
order
by
a
,
b
,
c
;
select
*
from
t1
order
by
a
,
b
,
c
;
explain
select
*
from
t1
order
by
a
desc
,
b
desc
,
c
desc
;
select
*
from
t1
order
by
a
desc
,
b
desc
,
c
desc
;
# test multiple ranges, NO_MAX_RANGE and EQ_RANGE
explain
select
*
from
t1
where
(
a
=
1
and
b
is
null
and
c
=
'b'
)
or
(
a
>
2
)
order
by
a
desc
;
select
*
from
t1
where
(
a
=
1
and
b
=
1
and
c
=
'b'
)
or
(
a
>
2
)
order
by
a
desc
;
# test NEAR_MAX, NO_MIN_RANGE
explain
select
*
from
t1
where
a
<
2
and
b
<=
1
order
by
a
desc
,
b
desc
;
select
*
from
t1
where
a
<
2
and
b
<=
1
order
by
a
desc
,
b
desc
;
# test HA_READ_AFTER_KEY (at the end of the file), NEAR_MIN
explain
select
*
from
t1
where
a
between
1
and
3
and
b
<=
1
order
by
a
desc
,
b
desc
;
select
*
from
t1
where
a
between
1
and
3
and
b
<=
1
order
by
a
desc
,
b
desc
;
# test HA_READ_AFTER_KEY (in the middle of the file)
explain
select
*
from
t1
where
a
between
0
and
1
order
by
a
desc
,
b
desc
;
select
*
from
t1
where
a
between
0
and
1
order
by
a
desc
,
b
desc
;
drop
table
t1
;
/* vim:set ft=sql sw=2 noet: */
sql/opt_range.cc
View file @
df298ac6
...
@@ -33,6 +33,7 @@
...
@@ -33,6 +33,7 @@
#include <m_ctype.h>
#include <m_ctype.h>
#include <nisam.h>
#include <nisam.h>
#include "sql_select.h"
#include "sql_select.h"
#include <assert.h>
#ifndef EXTRA_DEBUG
#ifndef EXTRA_DEBUG
...
@@ -289,7 +290,6 @@ typedef struct st_qsel_param {
...
@@ -289,7 +290,6 @@ typedef struct st_qsel_param {
max_key
[
MAX_KEY_LENGTH
+
MAX_FIELD_WIDTH
];
max_key
[
MAX_KEY_LENGTH
+
MAX_FIELD_WIDTH
];
}
PARAM
;
}
PARAM
;
static
SEL_TREE
*
get_mm_parts
(
PARAM
*
param
,
Field
*
field
,
static
SEL_TREE
*
get_mm_parts
(
PARAM
*
param
,
Field
*
field
,
Item_func
::
Functype
type
,
Item
*
value
,
Item_func
::
Functype
type
,
Item
*
value
,
Item_result
cmp_type
);
Item_result
cmp_type
);
...
@@ -2455,8 +2455,8 @@ int QUICK_SELECT::get_next()
...
@@ -2455,8 +2455,8 @@ int QUICK_SELECT::get_next()
if
((
error
=
file
->
index_first
(
record
)))
if
((
error
=
file
->
index_first
(
record
)))
DBUG_RETURN
(
error
);
// Empty table
DBUG_RETURN
(
error
);
// Empty table
if
(
cmp_next
(
range
)
==
0
)
if
(
cmp_next
(
range
)
==
0
)
DBUG_RETURN
(
0
);
// No matching records
DBUG_RETURN
(
0
);
range
=
0
;
// T
o next range
range
=
0
;
// No matching records; go t
o next range
continue
;
continue
;
}
}
if
((
result
=
file
->
index_read
(
record
,(
byte
*
)
range
->
min_key
,
if
((
result
=
file
->
index_read
(
record
,(
byte
*
)
range
->
min_key
,
...
@@ -2516,6 +2516,158 @@ int QUICK_SELECT::cmp_next(QUICK_RANGE *range)
...
@@ -2516,6 +2516,158 @@ int QUICK_SELECT::cmp_next(QUICK_RANGE *range)
return
(
range
->
flag
&
NEAR_MAX
)
?
1
:
0
;
// Exact match
return
(
range
->
flag
&
NEAR_MAX
)
?
1
:
0
;
// Exact match
}
}
/*
* This is a hack: we inherit from QUICK_SELECT so that we can use the
* get_next() interface, but we have to hold a pointer to the original
* QUICK_SELECT because its data are used all over the place. What
* should be done is to factor out the data that is needed into a base
* class (QUICK_SELECT), and then have two subclasses (_ASC and _DESC)
* which handle the ranges and implement the get_next() function. But
* for now, this seems to work right at least.
*/
QUICK_SELECT_DESC
::
QUICK_SELECT_DESC
(
QUICK_SELECT
*
q
)
:
QUICK_SELECT
(
*
q
),
quick
(
q
),
rev_it
(
rev_ranges
)
{
bool
not_read_after_key
=
file
->
option_flag
()
&
HA_NOT_READ_AFTER_KEY
;
for
(
QUICK_RANGE
*
r
=
it
++
;
r
;
r
=
it
++
)
{
rev_ranges
.
push_front
(
r
);
if
(
not_read_after_key
&&
range_reads_after_key
(
r
))
{
error
=
HA_ERR_UNSUPPORTED
;
break
;
}
}
}
int
QUICK_SELECT_DESC
::
get_next
()
{
DBUG_ENTER
(
"QUICK_SELECT_DESC::get_next"
);
/* The max key is handled as follows:
* - if there is NO_MAX_RANGE, start at the end and move backwards
* - if it is an EQ_RANGE and max key covers the entire key, go directly
* to the key and read through it (sorting backwards is
* same as sorting forwards)
* - if it is NEAR_MAX, go to the key or next, step back once, and
* move backwards
* - otherwise (not NEAR_MAX == include the key), go after the key,
* step back once, and move backwards
*/
for
(;;)
{
int
result
;
if
(
range
)
{
// Already read through key
result
=
((
range
->
flag
&
EQ_RANGE
)
?
file
->
index_next_same
(
record
,
(
byte
*
)
range
->
min_key
,
range
->
min_length
)
:
file
->
index_prev
(
record
));
if
(
!
result
)
{
if
(
cmp_prev
(
*
rev_it
.
ref
())
==
0
)
DBUG_RETURN
(
0
);
}
else
if
(
result
!=
HA_ERR_END_OF_FILE
)
DBUG_RETURN
(
result
);
}
if
(
!
(
range
=
rev_it
++
))
DBUG_RETURN
(
HA_ERR_END_OF_FILE
);
// All ranges used
if
(
range
->
flag
&
NO_MAX_RANGE
)
// Read last record
{
int
error
;
if
((
error
=
file
->
index_last
(
record
)))
DBUG_RETURN
(
error
);
// Empty table
if
(
cmp_prev
(
range
)
==
0
)
DBUG_RETURN
(
0
);
range
=
0
;
// No matching records; go to next range
continue
;
}
if
(
range
->
flag
&
EQ_RANGE
&&
head
->
key_info
[
index
].
key_length
==
range
->
max_length
)
{
result
=
file
->
index_read
(
record
,
(
byte
*
)
range
->
max_key
,
range
->
max_length
,
HA_READ_KEY_EXACT
);
}
else
{
dbug_assert
(
range
->
flag
&
NEAR_MAX
||
range_reads_after_key
(
range
));
/* Note: even if max_key is only a prefix, HA_READ_AFTER_KEY will
* do the right thing - go past all keys which match the prefix */
file
->
index_read
(
record
,
(
byte
*
)
range
->
max_key
,
range
->
max_length
,
((
range
->
flag
&
NEAR_MAX
)
?
HA_READ_KEY_OR_PREV
:
HA_READ_AFTER_KEY
));
result
=
file
->
index_prev
(
record
);
}
if
(
result
)
{
if
(
result
!=
HA_ERR_KEY_NOT_FOUND
)
DBUG_RETURN
(
result
);
range
=
0
;
// Not found, to next range
continue
;
}
if
(
cmp_prev
(
range
)
==
0
)
{
if
(
range
->
flag
==
(
UNIQUE_RANGE
|
EQ_RANGE
))
range
=
0
;
// Stop searching
DBUG_RETURN
(
0
);
// Found key is in range
}
range
=
0
;
// To next range
}
DBUG_RETURN
(
HA_ERR_END_OF_FILE
);
}
/*
* Returns 0 if found key is inside range (found key >= range->min_key).
*/
int
QUICK_SELECT_DESC
::
cmp_prev
(
QUICK_RANGE
*
range
)
{
if
(
range
->
flag
&
NO_MIN_RANGE
)
return
(
0
);
/* key can't be to small */
KEY_PART
*
key_part
=
quick
->
key_parts
;
for
(
char
*
key
=
range
->
min_key
,
*
end
=
key
+
range
->
min_length
;
key
<
end
;
key
+=
key_part
++->
part_length
)
{
int
cmp
;
if
(
key_part
->
null_bit
)
{
// this key part allows null values; NULL is lower than everything else
if
(
*
key
++
)
{
// the range is expecting a null value
if
(
!
key_part
->
field
->
is_null
())
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
}
if
((
cmp
=
key_part
->
field
->
key_cmp
((
byte
*
)
key
,
key_part
->
part_length
))
>
0
)
return
0
;
if
(
cmp
<
0
)
return
1
;
}
return
(
range
->
flag
&
NEAR_MIN
)
?
1
:
0
;
// Exact match
}
/*
* True if this range will require using HA_READ_AFTER_KEY
*/
bool
QUICK_SELECT_DESC
::
range_reads_after_key
(
QUICK_RANGE
*
range
)
{
// See comment in get_next()
return
range
->
flag
&
(
NO_MAX_RANGE
|
NEAR_MAX
)
?
1
:
(
range
->
flag
&
EQ_RANGE
&&
head
->
key_info
[
index
].
key_length
==
range
->
max_length
)
?
0
:
1
;
}
/*****************************************************************************
/*****************************************************************************
** Print a quick range for debugging
** Print a quick range for debugging
** TODO:
** TODO:
...
...
sql/opt_range.h
View file @
df298ac6
...
@@ -80,6 +80,20 @@ class QUICK_SELECT {
...
@@ -80,6 +80,20 @@ class QUICK_SELECT {
bool
unique_key_range
();
bool
unique_key_range
();
};
};
class
QUICK_SELECT_DESC
:
public
QUICK_SELECT
{
public:
QUICK_SELECT_DESC
(
QUICK_SELECT
*
q
);
int
get_next
();
private:
int
cmp_prev
(
QUICK_RANGE
*
range
);
bool
range_reads_after_key
(
QUICK_RANGE
*
range
);
QUICK_SELECT
*
quick
;
List
<
QUICK_RANGE
>
rev_ranges
;
List_iterator
<
QUICK_RANGE
>
rev_it
;
};
class
SQL_SELECT
:
public
Sql_alloc
{
class
SQL_SELECT
:
public
Sql_alloc
{
public:
public:
QUICK_SELECT
*
quick
;
// If quick-select used
QUICK_SELECT
*
quick
;
// If quick-select used
...
...
sql/sql_select.cc
View file @
df298ac6
...
@@ -5248,10 +5248,20 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
...
@@ -5248,10 +5248,20 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
if
(
ref_key
>=
0
)
if
(
ref_key
>=
0
)
{
{
int
order_direction
;
/* Check if we get the rows in requested sorted order by using the key */
/* Check if we get the rows in requested sorted order by using the key */
if
((
usable_keys
&
((
key_map
)
1
<<
ref_key
))
&&
if
((
usable_keys
&
((
key_map
)
1
<<
ref_key
))
&&
test_if_order_by_key
(
order
,
table
,
ref_key
)
==
1
)
(
order_direction
=
test_if_order_by_key
(
order
,
table
,
ref_key
)))
{
if
(
order_direction
==
-
1
&&
select
&&
select
->
quick
)
{
// ORDER BY ref_key DESC
select
->
quick
=
new
QUICK_SELECT_DESC
(
select
->
quick
);
if
(
select
->
quick
->
error
)
DBUG_RETURN
(
0
);
}
DBUG_RETURN
(
1
);
/* No need to sort */
DBUG_RETURN
(
1
);
/* No need to sort */
}
}
}
else
else
{
{
...
...
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