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
7dd4eb71
Commit
7dd4eb71
authored
Jan 12, 2002
by
monty@tik.mysql.fi
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added support of null keys in HEAP tables
Added ORDER BY optimization
parent
47408baa
Changes
31
Show whitespace changes
Inline
Side-by-side
Showing
31 changed files
with
547 additions
and
148 deletions
+547
-148
Docs/manual.texi
Docs/manual.texi
+145
-44
heap/_check.c
heap/_check.c
+4
-2
heap/heapdef.h
heap/heapdef.h
+1
-0
heap/hp_hash.c
heap/hp_hash.c
+82
-6
heap/hp_open.c
heap/hp_open.c
+4
-0
heap/hp_test2.c
heap/hp_test2.c
+32
-7
heap/hp_write.c
heap/hp_write.c
+3
-1
include/heap.h
include/heap.h
+3
-1
include/my_base.h
include/my_base.h
+2
-1
isam/static.c
isam/static.c
+1
-1
myisam/mi_static.c
myisam/mi_static.c
+1
-1
sql/Makefile.am
sql/Makefile.am
+2
-2
sql/ha_berkeley.cc
sql/ha_berkeley.cc
+31
-0
sql/ha_berkeley.h
sql/ha_berkeley.h
+2
-1
sql/ha_heap.cc
sql/ha_heap.cc
+12
-1
sql/ha_heap.h
sql/ha_heap.h
+1
-1
sql/ha_innodb.cc
sql/ha_innodb.cc
+19
-1
sql/ha_innodb.h
sql/ha_innodb.h
+16
-14
sql/ha_isam.cc
sql/ha_isam.cc
+9
-0
sql/ha_isam.h
sql/ha_isam.h
+2
-1
sql/ha_isammrg.h
sql/ha_isammrg.h
+3
-2
sql/ha_myisam.cc
sql/ha_myisam.cc
+30
-19
sql/ha_myisam.h
sql/ha_myisam.h
+11
-4
sql/ha_myisammrg.cc
sql/ha_myisammrg.cc
+9
-0
sql/ha_myisammrg.h
sql/ha_myisammrg.h
+2
-1
sql/handler.cc
sql/handler.cc
+1
-1
sql/handler.h
sql/handler.h
+5
-2
sql/mysqld.cc
sql/mysqld.cc
+1
-1
sql/sql_delete.cc
sql/sql_delete.cc
+1
-1
sql/sql_select.cc
sql/sql_select.cc
+109
-30
sql/sql_select.h
sql/sql_select.h
+3
-2
No files found.
Docs/manual.texi
View file @
7dd4eb71
...
@@ -750,7 +750,7 @@ Large server clusters using replication are in production use, with
...
@@ -750,7 +750,7 @@ Large server clusters using replication are in production use, with
good results. Work on enhanced replication features is continuing
good results. Work on enhanced replication features is continuing
in MySQL 4.0.
in MySQL 4.0.
@item @code{InnoDB} tables --
Gamma
@item @code{InnoDB} tables --
Stable
While the @code{InnoDB} transactional table handler is a fairly recent
While the @code{InnoDB} transactional table handler is a fairly recent
addition to @code{MySQL}, it appears to work well and is already being
addition to @code{MySQL}, it appears to work well and is already being
used in some large, heavy load production systems.
used in some large, heavy load production systems.
...
@@ -3692,9 +3692,6 @@ Allow users to change startup options without taking down the server.
...
@@ -3692,9 +3692,6 @@ Allow users to change startup options without taking down the server.
@item
@item
Fail safe replication.
Fail safe replication.
@item
@item
More functions for full-text search.
@xref{Fulltext TODO}.
@item
New key cache
New key cache
@item
@item
New table definition file format (@code{.frm} files) This will enable us
New table definition file format (@code{.frm} files) This will enable us
...
@@ -3727,9 +3724,6 @@ When using @code{SET CHARACTER SET} we should translate the whole query
...
@@ -3727,9 +3724,6 @@ When using @code{SET CHARACTER SET} we should translate the whole query
at once and not only strings. This will enable users to use the translated
at once and not only strings. This will enable users to use the translated
characters in database, table and column names.
characters in database, table and column names.
@item
@item
Add a portable interface over @code{gethostbyaddr_r()} so that we can change
@code{ip_to_hostname()} to not block other threads while doing DNS lookups.
@item
Add @code{record_in_range()} method to @code{MERGE} tables to be
Add @code{record_in_range()} method to @code{MERGE} tables to be
able to choose the right index when there is many to choose from. We should
able to choose the right index when there is many to choose from. We should
also extend the info interface to get the key distribution for each index,
also extend the info interface to get the key distribution for each index,
...
@@ -3861,15 +3855,6 @@ Don't add automatic @code{DEFAULT} values to columns. Give an error when using
...
@@ -3861,15 +3855,6 @@ Don't add automatic @code{DEFAULT} values to columns. Give an error when using
an @code{INSERT} that doesn't contain a column that doesn't have a
an @code{INSERT} that doesn't contain a column that doesn't have a
@code{DEFAULT}.
@code{DEFAULT}.
@item
@item
Caching of queries and results. This should be done as a separated
module that examines each query and if this is query is in the cache
the cached result should be returned. When one updates a table one
should remove as few queries as possible from the cache.
This should give a big speed bost on machines with much RAM where
queries are often repeated (like WWW applications).
One idea would be to only cache queries of type:
@code{SELECT CACHED ...}
@item
Fix @file{libmysql.c} to allow two @code{mysql_query()} commands in a row
Fix @file{libmysql.c} to allow two @code{mysql_query()} commands in a row
without reading results or give a nice error message when one does this.
without reading results or give a nice error message when one does this.
@item
@item
...
@@ -3934,10 +3919,7 @@ ADD_TO_SET(value,set) and REMOVE_FROM_SET(value,set)
...
@@ -3934,10 +3919,7 @@ ADD_TO_SET(value,set) and REMOVE_FROM_SET(value,set)
Add use of @code{t1 JOIN t2 ON ...} and @code{t1 JOIN t2 USING ...}
Add use of @code{t1 JOIN t2 ON ...} and @code{t1 JOIN t2 USING ...}
Currently, you can only use this syntax with @code{LEFT JOIN}.
Currently, you can only use this syntax with @code{LEFT JOIN}.
@item
@item
Add full support for @code{unsigned long long} type.
Many more variables for @code{show status}. Records reads and
@item
Many more variables for @code{show status}. Counts for:
@code{INSERT}/@code{DELETE}/@code{UPDATE} statements. Records reads and
updated. Selects on 1 table and selects with joins. Mean number of
updated. Selects on 1 table and selects with joins. Mean number of
tables in select. Number of @code{ORDER BY} and @code{GROUP BY} queries.
tables in select. Number of @code{ORDER BY} and @code{GROUP BY} queries.
@item
@item
...
@@ -3952,7 +3934,7 @@ should be implemented.
...
@@ -3952,7 +3934,7 @@ should be implemented.
@item
@item
Add support for UNICODE.
Add support for UNICODE.
@item
@item
@code{NATURAL JOIN}
and @code{UNION JOIN}
@code{NATURAL JOIN}
.
@item
@item
Allow @code{select a from crash_me left join crash_me2 using (a)}; In this
Allow @code{select a from crash_me left join crash_me2 using (a)}; In this
case @code{a} is assumed to come from the @code{crash_me} table.
case @code{a} is assumed to come from the @code{crash_me} table.
...
@@ -4069,8 +4051,6 @@ Use of full calculation names in the order part. (For ACCESS97)
...
@@ -4069,8 +4051,6 @@ Use of full calculation names in the order part. (For ACCESS97)
@code{MINUS}, @code{INTERSECT} and @code{FULL OUTER JOIN}.
@code{MINUS}, @code{INTERSECT} and @code{FULL OUTER JOIN}.
(Currently @code{UNION} (in 4.0) and @code{LEFT OUTER JOIN} are supported)
(Currently @code{UNION} (in 4.0) and @code{LEFT OUTER JOIN} are supported)
@item
@item
Allow @code{UNIQUE} on fields that can be @code{NULL}.
@item
@code{SQL_OPTION MAX_SELECT_TIME=#} to put a time limit on a query.
@code{SQL_OPTION MAX_SELECT_TIME=#} to put a time limit on a query.
@item
@item
Make the update log to a database.
Make the update log to a database.
...
@@ -24578,6 +24558,7 @@ great tool to find out if this is a problem with your query.
...
@@ -24578,6 +24558,7 @@ great tool to find out if this is a problem with your query.
* Where optimisations:: How MySQL optimises @code{WHERE} clauses
* Where optimisations:: How MySQL optimises @code{WHERE} clauses
* DISTINCT optimisation:: How MySQL Optimises @code{DISTINCT}
* DISTINCT optimisation:: How MySQL Optimises @code{DISTINCT}
* LEFT JOIN optimisation:: How MySQL optimises @code{LEFT JOIN}
* LEFT JOIN optimisation:: How MySQL optimises @code{LEFT JOIN}
* ORDER BY optimisation::
* LIMIT optimisation:: How MySQL optimises @code{LIMIT}
* LIMIT optimisation:: How MySQL optimises @code{LIMIT}
* Insert speed:: Speed of @code{INSERT} queries
* Insert speed:: Speed of @code{INSERT} queries
* Update speed:: Speed of @code{UPDATE} queries
* Update speed:: Speed of @code{UPDATE} queries
...
@@ -25171,7 +25152,7 @@ MySQL will stop reading from t2 (for that particular row in t1)
...
@@ -25171,7 +25152,7 @@ MySQL will stop reading from t2 (for that particular row in t1)
when the first row in t2 is found.
when the first row in t2 is found.
@node LEFT JOIN optimisation,
LIMIT
optimisation, DISTINCT optimisation, Query Speed
@node LEFT JOIN optimisation,
ORDER BY
optimisation, DISTINCT optimisation, Query Speed
@subsection How MySQL Optimises @code{LEFT JOIN} and @code{RIGHT JOIN}
@subsection How MySQL Optimises @code{LEFT JOIN} and @code{RIGHT JOIN}
@findex LEFT JOIN
@findex LEFT JOIN
...
@@ -25237,7 +25218,119 @@ SELECT * FROM b,a LEFT JOIN c ON (c.key=a.key) LEFT JOIN d (d.key=a.key) WHERE b
...
@@ -25237,7 +25218,119 @@ SELECT * FROM b,a LEFT JOIN c ON (c.key=a.key) LEFT JOIN d (d.key=a.key) WHERE b
@end example
@end example
@node LIMIT optimisation, Insert speed, LEFT JOIN optimisation, Query Speed
@node ORDER BY optimisation, LIMIT optimisation, LEFT JOIN optimisation, Query Speed
@subsection How MySQL Optimises @code{ORDER BY}
In some cases MySQL can uses index to satisfy an @code{ORDER BY} or
@code{GROUP BY} request without doing any extra sorting.
The index can also be used even if the @code{ORDER BY} doesn't match the
index exactly, as long as all the unused index parts and all the extra
are @code{ORDER BY} columns are constants in the @code{WHERE}
clause. The following queries will use the index to resolve the
@code{ORDER BY} / @code{GROUP BY} part:
@example
SELECT * FROM t1 ORDER BY key_part1,key_part2,...
SELECT * FROM t1 WHERE key_part1=constant ORDER BY key_part2
SELECT * FROM t1 WHERE key_part1=constant GROUP BY key_part2
SELECT * FROM t1 ORDER BY key_part1 DESC,key_part2 DESC
SELECT * FROM t1 WHERE key_part1=1 ORDER BY key_part1 DESC,key_part2 DESC
@end example
Some cases where MySQL can NOT use indexes to resolve the @code{ORDER
BY}: (Note that MySQL will still use indexes to find the rows that
matches the where clause):
@itemize @bullet
@item
You are doing an @code{ORDER BY} on different keys:
@code{SELECT * FROM t1 ORDER BY key1,key2}
@item
You are doing an @code{ORDER BY} on not following key parts.
@code{SELECT * FROM t1 WHERE key2=constant ORDER BY key_part2}
@item
You are mixing @code{ASC} and @code{DESC}.
@code{SELECT * FROM t1 ORDER BY key_part1 DESC,key_part2 ASC}
@item
The key used to fetch the rows are not the same one that is used to
do the @code{ORDER BY}:
@code{SELECT * FROM t1 WHERE key2=constant ORDER BY key1}
@item
You are joining many tables and the columns you are doing an @code{ORDER
BY} on are not all from the first not-const table that is used to
retrieve rows (This is the first table in the @code{EXPLAIN} output which
doesn't use a @code{const} row fetch method).
@item
You have different @code{ORDER BY} and @code{GROUP BY} expressions.
@item
The used table index is an index type that doesn't store rows in order.
(Like index in @code{HEAP} tables).
@end itemize
In the cases where MySQL have to sort the result, it uses the following
algorithm:
@itemize @bullet
@item
Read all rows according to key or by table scanning.
Rows that doesn't match the WHERE clause are skipped.
@item
Store the sort-key in a buffer (of size @code{sort_buffer}).
@item
When the buffer gets full, run a qsort on it and store the result
in a temporary file. Save a pointer to the sorted block.
(In the case where all rows fits into the sort buffer, no temporary
file is created)
@item
Repeat the above until all rows have been read.
@item
Do a multi-merge of up to @code{MERGEBUFF} (7) regions to one block in
another temporary file. Repeat until all blocks from the first file
are in the second file.
@item
Repeat the following until there is less than @code{MERGEBUFF2} (15)
blocks left.
@item
On the last multi-merge, only the pointer to the row (last part of
the sort-key) is written to a result file.
@item
Now the code in @file{sql/records.cc} will be used to read through them
in sorted order by using the row pointers in the result file. To
optimize this, we read in a big block of row pointers, sort these and
then we read the rows in the sorted order into a row buffer
(@code{record_rnd_buffer}) .
@end itemize
You can with @code{EXPLAIN SELECT ... ORDER BY} check if MySQL can use
indexes to resolve the query. If you get @code{Using filesort} in the
@code{extra} column, then MySQL can't use indexes to resolve the
@code{ORDER BY}. @xref{EXPLAIN}.
If you want to have a higher @code{ORDER BY} speed, you should first
see if you can get MySQL to use indexes instead of having to do an extra
sorting phase. If this is not possible, then you can do:
@itemize @bullet
@item
Increase the size of the @code{sort_buffer} variable.
@item
Increase the size of the @code{record_rnd_buffer} variable.
@item
Change @code{tmpdir} to point to a dedicated disk with lots of empty space.
@end itemize
@node LIMIT optimisation, Insert speed, ORDER BY optimisation, Query Speed
@subsection How MySQL Optimises @code{LIMIT}
@subsection How MySQL Optimises @code{LIMIT}
@findex LIMIT
@findex LIMIT
...
@@ -25986,19 +26079,9 @@ SELECT MIN(key_part2),MAX(key_part2) FROM table_name where key_part1=10
...
@@ -25986,19 +26079,9 @@ SELECT MIN(key_part2),MAX(key_part2) FROM table_name where key_part1=10
@item
@item
Sort or group a table if the sorting or grouping is done on a leftmost
Sort or group a table if the sorting or grouping is done on a leftmost
prefix of a usable key (for example, @code{ORDER BY key_part_1,key_part_2 }). The
prefix of a usable key (for example, @code{ORDER BY
key is read in reverse order if all key parts are followed by @code{DESC}.
key_part_1,key_part_2 }). The key is read in reverse order if all key
parts are followed by @code{DESC}. @xref{ORDER BY optimisation}.
The index can also be used even if the @code{ORDER BY} doesn't match the index
exactly, as long as all the unused index parts and all the extra
are @code{ORDER BY} columns are constants in the @code{WHERE} clause. The
following queries will use the index to resolve the @code{ORDER BY} part:
@example
SELECT * FROM foo ORDER BY key_part1,key_part2,key_part3;
SELECT * FROM foo WHERE column=constant ORDER BY column, key_part1;
SELECT * FROM foo WHERE key_part1=const GROUP BY key_part2;
@end example
@item
@item
In some cases a query can be optimised to retrieve values without
In some cases a query can be optimised to retrieve values without
...
@@ -33355,7 +33438,12 @@ DELETE [LOW_PRIORITY | QUICK] FROM table_name
...
@@ -33355,7 +33438,12 @@ DELETE [LOW_PRIORITY | QUICK] FROM table_name
or
or
DELETE [LOW_PRIORITY | QUICK] table_name[.*] [table_name[.*] ...] FROM
DELETE [LOW_PRIORITY | QUICK] table_name[.*] [,table_name[.*] ...] FROM
table-references [WHERE where_definition]
or
DELETE [LOW_PRIORITY | QUICK] FROM table_name[.*], [table_name[.*] ...] USING
table-references [WHERE where_definition]
table-references [WHERE where_definition]
@end example
@end example
...
@@ -33392,18 +33480,23 @@ TABLE} statement or the @code{myisamchk} utility to reorganise tables.
...
@@ -33392,18 +33480,23 @@ TABLE} statement or the @code{myisamchk} utility to reorganise tables.
@code{OPTIMIZE TABLE} is easier, but @code{myisamchk} is faster. See
@code{OPTIMIZE TABLE} is easier, but @code{myisamchk} is faster. See
@ref{OPTIMIZE TABLE, , @code{OPTIMIZE TABLE}} and @ref{Optimisation}.
@ref{OPTIMIZE TABLE, , @code{OPTIMIZE TABLE}} and @ref{Optimisation}.
The multi table delete format is supported starting from MySQL 4.0.0.
The first multi table delete format is supported starting from MySQL 4.0.0.
The second multi table delete format is supported starting from MySQL 4.0.2.
The idea is that only matching rows from the tables listed
@strong{before} the
The idea is that only matching rows from the tables listed
@
code{FROM} clause is deleted. The effect is that you can delete row
s
@
strong{before} the @code{FROM} or before the @code{USING} clause i
s
from many tables at the same time and also have additional tables that
deleted. The effect is that you can delete rows from many tables at the
are used for searching.
same time and also have additional tables that
are used for searching.
The @code{.*} after the table names is there just to be compatible with
The @code{.*} after the table names is there just to be compatible with
@code{Access}:
@code{Access}:
@example
@example
DELETE t1,t2 FROM t1,t2,t3 WHERE t1.id=t2.id AND t2.id=t3.id
DELETE t1,t2 FROM t1,t2,t3 WHERE t1.id=t2.id AND t2.id=t3.id
or
DELETE FROM t1,t2 USING t1,t2,t3 WHERE t1.id=t2.id AND t2.id=t3.id
@end example
@end example
In the above case we delete matching rows just from tables @code{t1} and
In the above case we delete matching rows just from tables @code{t1} and
...
@@ -48028,10 +48121,18 @@ Our TODO section contains what we plan to have in 4.0. @xref{TODO MySQL 4.0}.
...
@@ -48028,10 +48121,18 @@ Our TODO section contains what we plan to have in 4.0. @xref{TODO MySQL 4.0}.
@itemize @bullet
@itemize @bullet
@item
@item
Added support for @code{NULL} keys in HEAP tables.
@item
Use index for @code{ORDER BY} in queries of type:
@code{SELECT * FROM t1 WHERE key_part1=1 ORDER BY key_part1 DESC,key_part2 DESC}
@item
Fixed bug in @code{FLUSH QUERY CACHE}.
Fixed bug in @code{FLUSH QUERY CACHE}.
@item
@item
Added @code{CAST()} and @code{CONVERT()} functions.
Added @code{CAST()} and @code{CONVERT()} functions.
@item
@item
@code{CREATE ... SELECT} on @code{DATE} and @code{TIME} functions now
create columns of the expected type.
@item
Changed order of how keys are created in tables.
Changed order of how keys are created in tables.
@item
@item
Added a new columns @code{Null} and @code{Index_type} to @code{SHOW INDEX}.
Added a new columns @code{Null} and @code{Index_type} to @code{SHOW INDEX}.
heap/_check.c
View file @
7dd4eb71
...
@@ -79,9 +79,11 @@ static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records,
...
@@ -79,9 +79,11 @@ static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records,
}
}
DBUG_PRINT
(
"info"
,
DBUG_PRINT
(
"info"
,
(
"records: %ld seeks: %d max links: %d hitrate: %.2f"
,
(
"records: %ld seeks: %d max links: %d hitrate: %.2f"
,
records
,
seek
,
max_links
,(
float
)
seek
/
(
float
)
(
records
?
records
:
1
)));
records
,
seek
,
max_links
,
(
float
)
seek
/
(
float
)
(
records
?
records
:
1
)));
if
(
print_status
)
if
(
print_status
)
printf
(
"Key: %d records: %ld seeks: %d max links: %d hitrate: %.2f
\n
"
,
printf
(
"Key: %d records: %ld seeks: %d max links: %d hitrate: %.2f
\n
"
,
keynr
,
records
,
seek
,
max_links
,
(
float
)
seek
/
(
float
)
records
);
keynr
,
records
,
seek
,
max_links
,
(
float
)
seek
/
(
float
)
(
records
?
records
:
1
));
return
error
;
return
error
;
}
}
heap/heapdef.h
View file @
7dd4eb71
...
@@ -70,6 +70,7 @@ extern int _hp_rec_key_cmp(HP_KEYDEF *keydef,const byte *rec1,
...
@@ -70,6 +70,7 @@ extern int _hp_rec_key_cmp(HP_KEYDEF *keydef,const byte *rec1,
extern
int
_hp_key_cmp
(
HP_KEYDEF
*
keydef
,
const
byte
*
rec
,
extern
int
_hp_key_cmp
(
HP_KEYDEF
*
keydef
,
const
byte
*
rec
,
const
byte
*
key
);
const
byte
*
key
);
extern
void
_hp_make_key
(
HP_KEYDEF
*
keydef
,
byte
*
key
,
const
byte
*
rec
);
extern
void
_hp_make_key
(
HP_KEYDEF
*
keydef
,
byte
*
key
,
const
byte
*
rec
);
extern
my_bool
hp_if_null_in_key
(
HP_KEYDEF
*
keyinfo
,
const
byte
*
record
);
extern
int
_hp_close
(
register
HP_INFO
*
info
);
extern
int
_hp_close
(
register
HP_INFO
*
info
);
extern
void
_hp_clear
(
HP_SHARE
*
info
);
extern
void
_hp_clear
(
HP_SHARE
*
info
);
...
...
heap/hp_hash.c
View file @
7dd4eb71
...
@@ -158,11 +158,22 @@ ulong _hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
...
@@ -158,11 +158,22 @@ ulong _hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
{
{
uchar
*
pos
=
(
uchar
*
)
key
;
uchar
*
pos
=
(
uchar
*
)
key
;
key
+=
seg
->
length
;
key
+=
seg
->
length
;
if
(
seg
->
null_bit
)
{
key
++
;
/* Skipp null byte */
if
(
*
pos
)
/* Found null */
{
nr
^=
(
nr
<<
1
)
|
1
;
continue
;
}
pos
++
;
}
if
(
seg
->
type
==
HA_KEYTYPE_TEXT
)
if
(
seg
->
type
==
HA_KEYTYPE_TEXT
)
{
{
for
(;
pos
<
(
uchar
*
)
key
;
pos
++
)
for
(;
pos
<
(
uchar
*
)
key
;
pos
++
)
{
{
nr
^=
(
ulong
)
((((
uint
)
nr
&
63
)
+
nr2
)
*
((
uint
)
my_sort_order
[(
uint
)
*
pos
]))
+
(
nr
<<
8
);
nr
^=
(
ulong
)
((((
uint
)
nr
&
63
)
+
nr2
)
*
((
uint
)
my_sort_order
[(
uint
)
*
pos
]))
+
(
nr
<<
8
);
nr2
+=
3
;
nr2
+=
3
;
}
}
}
}
...
@@ -170,7 +181,7 @@ ulong _hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
...
@@ -170,7 +181,7 @@ ulong _hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
{
{
for
(;
pos
<
(
uchar
*
)
key
;
pos
++
)
for
(;
pos
<
(
uchar
*
)
key
;
pos
++
)
{
{
nr
^=
(
ulong
)
((((
uint
)
nr
&
63
)
+
nr2
)
*
((
uint
)
*
pos
))
+
(
nr
<<
8
);
nr
^=
(
ulong
)
((((
uint
)
nr
&
63
)
+
nr2
)
*
((
uint
)
*
pos
))
+
(
nr
<<
8
);
nr2
+=
3
;
nr2
+=
3
;
}
}
}
}
...
@@ -188,11 +199,20 @@ ulong _hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
...
@@ -188,11 +199,20 @@ ulong _hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
for
(
seg
=
keydef
->
seg
,
endseg
=
seg
+
keydef
->
keysegs
;
seg
<
endseg
;
seg
++
)
for
(
seg
=
keydef
->
seg
,
endseg
=
seg
+
keydef
->
keysegs
;
seg
<
endseg
;
seg
++
)
{
{
uchar
*
pos
=
(
uchar
*
)
rec
+
seg
->
start
,
*
end
=
pos
+
seg
->
length
;
uchar
*
pos
=
(
uchar
*
)
rec
+
seg
->
start
,
*
end
=
pos
+
seg
->
length
;
if
(
seg
->
null_bit
)
{
if
(
rec
[
seg
->
null_pos
]
&
seg
->
null_bit
)
{
nr
^=
(
nr
<<
1
)
|
1
;
continue
;
}
}
if
(
seg
->
type
==
HA_KEYTYPE_TEXT
)
if
(
seg
->
type
==
HA_KEYTYPE_TEXT
)
{
{
for
(;
pos
<
end
;
pos
++
)
for
(;
pos
<
end
;
pos
++
)
{
{
nr
^=
(
ulong
)
((((
uint
)
nr
&
63
)
+
nr2
)
*
((
uint
)
my_sort_order
[(
uint
)
*
pos
]))
+
(
nr
<<
8
);
nr
^=
(
ulong
)
((((
uint
)
nr
&
63
)
+
nr2
)
*
((
uint
)
my_sort_order
[(
uint
)
*
pos
]))
+
(
nr
<<
8
);
nr2
+=
3
;
nr2
+=
3
;
}
}
}
}
...
@@ -234,6 +254,16 @@ ulong _hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
...
@@ -234,6 +254,16 @@ ulong _hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
{
{
uchar
*
pos
=
(
uchar
*
)
key
;
uchar
*
pos
=
(
uchar
*
)
key
;
key
+=
seg
->
length
;
key
+=
seg
->
length
;
if
(
seg
->
null_bit
)
{
key
++
;
if
(
*
pos
)
{
nr
^=
(
nr
<<
1
)
|
1
;
continue
;
}
pos
++
;
}
if
(
seg
->
type
==
HA_KEYTYPE_TEXT
)
if
(
seg
->
type
==
HA_KEYTYPE_TEXT
)
{
{
for
(;
pos
<
(
uchar
*
)
key
;
pos
++
)
for
(;
pos
<
(
uchar
*
)
key
;
pos
++
)
...
@@ -264,6 +294,14 @@ ulong _hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
...
@@ -264,6 +294,14 @@ ulong _hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
for
(
seg
=
keydef
->
seg
,
endseg
=
seg
+
keydef
->
keysegs
;
seg
<
endseg
;
seg
++
)
for
(
seg
=
keydef
->
seg
,
endseg
=
seg
+
keydef
->
keysegs
;
seg
<
endseg
;
seg
++
)
{
{
uchar
*
pos
=
(
uchar
*
)
rec
+
seg
->
start
,
*
end
=
pos
+
seg
->
length
;
uchar
*
pos
=
(
uchar
*
)
rec
+
seg
->
start
,
*
end
=
pos
+
seg
->
length
;
if
(
seg
->
null_bit
)
{
if
(
rec
[
seg
->
null_pos
]
&
seg
->
null_bit
)
{
nr
^=
(
nr
<<
1
)
|
1
;
continue
;
}
}
if
(
seg
->
type
==
HA_KEYTYPE_TEXT
)
if
(
seg
->
type
==
HA_KEYTYPE_TEXT
)
{
{
for
(
;
pos
<
end
;
pos
++
)
for
(
;
pos
<
end
;
pos
++
)
...
@@ -295,6 +333,14 @@ int _hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2)
...
@@ -295,6 +333,14 @@ int _hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2)
for
(
seg
=
keydef
->
seg
,
endseg
=
seg
+
keydef
->
keysegs
;
seg
<
endseg
;
seg
++
)
for
(
seg
=
keydef
->
seg
,
endseg
=
seg
+
keydef
->
keysegs
;
seg
<
endseg
;
seg
++
)
{
{
if
(
seg
->
null_bit
)
{
if
((
rec1
[
seg
->
null_pos
]
&
seg
->
null_bit
)
!=
(
rec2
[
seg
->
null_pos
]
&
seg
->
null_bit
))
return
1
;
if
(
rec1
[
seg
->
null_pos
]
&
seg
->
null_bit
)
continue
;
}
if
(
seg
->
type
==
HA_KEYTYPE_TEXT
)
if
(
seg
->
type
==
HA_KEYTYPE_TEXT
)
{
{
if
(
my_sortcmp
(
rec1
+
seg
->
start
,
rec2
+
seg
->
start
,
seg
->
length
))
if
(
my_sortcmp
(
rec1
+
seg
->
start
,
rec2
+
seg
->
start
,
seg
->
length
))
...
@@ -309,14 +355,24 @@ int _hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2)
...
@@ -309,14 +355,24 @@ int _hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2)
return
0
;
return
0
;
}
}
/* Compare a key in a record to a hole key */
/* Compare a key in a record to a
w
hole key */
int
_hp_key_cmp
(
HP_KEYDEF
*
keydef
,
const
byte
*
rec
,
const
byte
*
key
)
int
_hp_key_cmp
(
HP_KEYDEF
*
keydef
,
const
byte
*
rec
,
const
byte
*
key
)
{
{
HP_KEYSEG
*
seg
,
*
endseg
;
HP_KEYSEG
*
seg
,
*
endseg
;
for
(
seg
=
keydef
->
seg
,
endseg
=
seg
+
keydef
->
keysegs
;
seg
<
endseg
;
seg
++
)
for
(
seg
=
keydef
->
seg
,
endseg
=
seg
+
keydef
->
keysegs
;
seg
<
endseg
;
key
+=
(
seg
++
)
->
length
)
{
if
(
seg
->
null_bit
)
{
{
int
found_null
=
test
(
rec
[
seg
->
null_pos
]
&
seg
->
null_bit
);
if
(
found_null
!=
(
int
)
*
key
++
)
return
1
;
if
(
found_null
)
continue
;
}
if
(
seg
->
type
==
HA_KEYTYPE_TEXT
)
if
(
seg
->
type
==
HA_KEYTYPE_TEXT
)
{
{
if
(
my_sortcmp
(
rec
+
seg
->
start
,
key
,
seg
->
length
))
if
(
my_sortcmp
(
rec
+
seg
->
start
,
key
,
seg
->
length
))
...
@@ -327,7 +383,6 @@ int _hp_key_cmp(HP_KEYDEF *keydef, const byte *rec, const byte *key)
...
@@ -327,7 +383,6 @@ int _hp_key_cmp(HP_KEYDEF *keydef, const byte *rec, const byte *key)
if
(
bcmp
(
rec
+
seg
->
start
,
key
,
seg
->
length
))
if
(
bcmp
(
rec
+
seg
->
start
,
key
,
seg
->
length
))
return
1
;
return
1
;
}
}
key
+=
seg
->
length
;
}
}
return
0
;
return
0
;
}
}
...
@@ -341,7 +396,28 @@ void _hp_make_key(HP_KEYDEF *keydef, byte *key, const byte *rec)
...
@@ -341,7 +396,28 @@ void _hp_make_key(HP_KEYDEF *keydef, byte *key, const byte *rec)
for
(
seg
=
keydef
->
seg
,
endseg
=
seg
+
keydef
->
keysegs
;
seg
<
endseg
;
seg
++
)
for
(
seg
=
keydef
->
seg
,
endseg
=
seg
+
keydef
->
keysegs
;
seg
<
endseg
;
seg
++
)
{
{
if
(
seg
->
null_bit
)
*
key
++=
test
(
rec
[
seg
->
null_pos
]
&
seg
->
null_bit
);
memcpy
(
key
,
rec
+
seg
->
start
,(
size_t
)
seg
->
length
);
memcpy
(
key
,
rec
+
seg
->
start
,(
size_t
)
seg
->
length
);
key
+=
seg
->
length
;
key
+=
seg
->
length
;
}
}
}
}
/*
Test if any of the key parts are NULL.
Return:
1 if any of the key parts was NULL
0 otherwise
*/
my_bool
hp_if_null_in_key
(
HP_KEYDEF
*
keydef
,
const
byte
*
record
)
{
HP_KEYSEG
*
seg
,
*
endseg
;
for
(
seg
=
keydef
->
seg
,
endseg
=
seg
+
keydef
->
keysegs
;
seg
<
endseg
;
seg
++
)
{
if
(
seg
->
null_bit
&&
(
record
[
seg
->
null_pos
]
&
seg
->
null_bit
))
return
1
;
}
return
0
;
}
heap/hp_open.c
View file @
7dd4eb71
...
@@ -44,7 +44,11 @@ HP_INFO *heap_open(const char *name, int mode, uint keys, HP_KEYDEF *keydef,
...
@@ -44,7 +44,11 @@ HP_INFO *heap_open(const char *name, int mode, uint keys, HP_KEYDEF *keydef,
key_segs
+=
keydef
[
i
].
keysegs
;
key_segs
+=
keydef
[
i
].
keysegs
;
bzero
((
char
*
)
&
keydef
[
i
].
block
,
sizeof
(
keydef
[
i
].
block
));
bzero
((
char
*
)
&
keydef
[
i
].
block
,
sizeof
(
keydef
[
i
].
block
));
for
(
j
=
length
=
0
;
j
<
keydef
[
i
].
keysegs
;
j
++
)
for
(
j
=
length
=
0
;
j
<
keydef
[
i
].
keysegs
;
j
++
)
{
length
+=
keydef
[
i
].
seg
[
j
].
length
;
length
+=
keydef
[
i
].
seg
[
j
].
length
;
if
(
keydef
[
i
].
seg
[
j
].
null_bit
)
keydef
[
i
].
flag
|=
HA_NULL_PART_KEY
;
}
keydef
[
i
].
length
=
length
;
keydef
[
i
].
length
=
length
;
if
(
length
>
max_length
)
if
(
length
>
max_length
)
max_length
=
length
;
max_length
=
length
;
...
...
heap/hp_test2.c
View file @
7dd4eb71
...
@@ -30,7 +30,7 @@
...
@@ -30,7 +30,7 @@
#include <signal.h>
#include <signal.h>
#define MAX_RECORDS 100000
#define MAX_RECORDS 100000
#define MAX_KEYS
3
#define MAX_KEYS
4
static
int
get_options
(
int
argc
,
char
*
argv
[]);
static
int
get_options
(
int
argc
,
char
*
argv
[]);
static
int
rnd
(
int
max_value
);
static
int
rnd
(
int
max_value
);
...
@@ -40,16 +40,20 @@ static uint flag=0,verbose=0,testflag=0,recant=10000,silent=0;
...
@@ -40,16 +40,20 @@ static uint flag=0,verbose=0,testflag=0,recant=10000,silent=0;
static
uint
keys
=
MAX_KEYS
;
static
uint
keys
=
MAX_KEYS
;
static
uint16
key1
[
1001
];
static
uint16
key1
[
1001
];
static
my_bool
key3
[
MAX_RECORDS
];
static
my_bool
key3
[
MAX_RECORDS
];
static
int
reclength
=
39
;
static
int
calc_check
(
byte
*
buf
,
uint
length
);
static
int
calc_check
(
byte
*
buf
,
uint
length
);
static
void
make_record
(
char
*
record
,
uint
n1
,
uint
n2
,
uint
n3
,
const
char
*
mark
,
uint
count
);
/* Huvudprogrammet
*/
/* Main program
*/
int
main
(
int
argc
,
char
*
argv
[])
int
main
(
int
argc
,
char
*
argv
[])
{
{
register
uint
i
,
j
;
register
uint
i
,
j
;
uint
ant
,
n1
,
n2
,
n3
;
uint
ant
,
n1
,
n2
,
n3
;
uint
reclength
,
write_count
,
update
,
opt_delete
,
check2
,
dupp_keys
,
found_key
;
uint
write_count
,
update
,
opt_delete
,
check2
,
dupp_keys
,
found_key
;
int
error
;
int
error
;
ulong
pos
;
ulong
pos
;
unsigned
long
key_check
;
unsigned
long
key_check
;
...
@@ -66,7 +70,6 @@ int main(int argc, char *argv[])
...
@@ -66,7 +70,6 @@ int main(int argc, char *argv[])
filename2
=
"test2_2"
;
filename2
=
"test2_2"
;
file
=
file2
=
0
;
file
=
file2
=
0
;
get_options
(
argc
,
argv
);
get_options
(
argc
,
argv
);
reclength
=
37
;
write_count
=
update
=
opt_delete
=
0
;
write_count
=
update
=
opt_delete
=
0
;
key_check
=
0
;
key_check
=
0
;
...
@@ -77,21 +80,33 @@ int main(int argc, char *argv[])
...
@@ -77,21 +80,33 @@ int main(int argc, char *argv[])
keyinfo
[
0
].
seg
[
0
].
type
=
HA_KEYTYPE_BINARY
;
keyinfo
[
0
].
seg
[
0
].
type
=
HA_KEYTYPE_BINARY
;
keyinfo
[
0
].
seg
[
0
].
start
=
0
;
keyinfo
[
0
].
seg
[
0
].
start
=
0
;
keyinfo
[
0
].
seg
[
0
].
length
=
6
;
keyinfo
[
0
].
seg
[
0
].
length
=
6
;
keyinfo
[
0
].
seg
[
0
].
null_bit
=
0
;
keyinfo
[
1
].
seg
=
keyseg
+
1
;
keyinfo
[
1
].
seg
=
keyseg
+
1
;
keyinfo
[
1
].
keysegs
=
2
;
keyinfo
[
1
].
keysegs
=
2
;
keyinfo
[
1
].
flag
=
0
;
keyinfo
[
1
].
flag
=
0
;
keyinfo
[
1
].
seg
[
0
].
type
=
HA_KEYTYPE_BINARY
;
keyinfo
[
1
].
seg
[
0
].
type
=
HA_KEYTYPE_BINARY
;
keyinfo
[
1
].
seg
[
0
].
start
=
7
;
keyinfo
[
1
].
seg
[
0
].
start
=
7
;
keyinfo
[
1
].
seg
[
0
].
length
=
6
;
keyinfo
[
1
].
seg
[
0
].
length
=
6
;
keyinfo
[
1
].
seg
[
0
].
null_bit
=
0
;
keyinfo
[
1
].
seg
[
1
].
type
=
HA_KEYTYPE_TEXT
;
keyinfo
[
1
].
seg
[
1
].
type
=
HA_KEYTYPE_TEXT
;
keyinfo
[
1
].
seg
[
1
].
start
=
0
;
/*
Tv}delad nyckel
*/
keyinfo
[
1
].
seg
[
1
].
start
=
0
;
/*
key in two parts
*/
keyinfo
[
1
].
seg
[
1
].
length
=
6
;
keyinfo
[
1
].
seg
[
1
].
length
=
6
;
keyinfo
[
1
].
seg
[
1
].
null_bit
=
0
;
keyinfo
[
2
].
seg
=
keyseg
+
3
;
keyinfo
[
2
].
seg
=
keyseg
+
3
;
keyinfo
[
2
].
keysegs
=
1
;
keyinfo
[
2
].
keysegs
=
1
;
keyinfo
[
2
].
flag
=
HA_NOSAME
;
keyinfo
[
2
].
flag
=
HA_NOSAME
;
keyinfo
[
2
].
seg
[
0
].
type
=
HA_KEYTYPE_BINARY
;
keyinfo
[
2
].
seg
[
0
].
type
=
HA_KEYTYPE_BINARY
;
keyinfo
[
2
].
seg
[
0
].
start
=
12
;
keyinfo
[
2
].
seg
[
0
].
start
=
12
;
keyinfo
[
2
].
seg
[
0
].
length
=
8
;
keyinfo
[
2
].
seg
[
0
].
length
=
8
;
keyinfo
[
2
].
seg
[
0
].
null_bit
=
0
;
keyinfo
[
3
].
keysegs
=
1
;
keyinfo
[
3
].
flag
=
HA_NOSAME
;
keyinfo
[
3
].
seg
=
keyseg
+
4
;
keyinfo
[
3
].
seg
[
0
].
type
=
HA_KEYTYPE_BINARY
;
keyinfo
[
3
].
seg
[
0
].
start
=
37
;
keyinfo
[
3
].
seg
[
0
].
length
=
1
;
keyinfo
[
3
].
seg
[
0
].
null_bit
=
1
;
keyinfo
[
3
].
seg
[
0
].
null_pos
=
38
;
bzero
((
char
*
)
key1
,
sizeof
(
key1
));
bzero
((
char
*
)
key1
,
sizeof
(
key1
));
bzero
((
char
*
)
key3
,
sizeof
(
key3
));
bzero
((
char
*
)
key3
,
sizeof
(
key3
));
...
@@ -110,7 +125,7 @@ int main(int argc, char *argv[])
...
@@ -110,7 +125,7 @@ int main(int argc, char *argv[])
for
(
i
=
0
;
i
<
recant
;
i
++
)
for
(
i
=
0
;
i
<
recant
;
i
++
)
{
{
n1
=
rnd
(
1000
);
n2
=
rnd
(
100
);
n3
=
rnd
(
min
(
recant
*
5
,
MAX_RECORDS
));
n1
=
rnd
(
1000
);
n2
=
rnd
(
100
);
n3
=
rnd
(
min
(
recant
*
5
,
MAX_RECORDS
));
sprintf
(
record
,
"%6d:%4d:%8d:Pos: %4d "
,
n1
,
n2
,
n3
,
write_count
);
make_record
(
record
,
n1
,
n2
,
n3
,
"Pos"
,
write_count
);
if
(
heap_write
(
file
,
record
))
if
(
heap_write
(
file
,
record
))
{
{
...
@@ -191,7 +206,7 @@ int main(int argc, char *argv[])
...
@@ -191,7 +206,7 @@ int main(int argc, char *argv[])
for
(
i
=
0
;
i
<
write_count
/
10
;
i
++
)
for
(
i
=
0
;
i
<
write_count
/
10
;
i
++
)
{
{
n1
=
rnd
(
1000
);
n2
=
rnd
(
100
);
n3
=
rnd
(
min
(
recant
*
2
,
MAX_RECORDS
));
n1
=
rnd
(
1000
);
n2
=
rnd
(
100
);
n3
=
rnd
(
min
(
recant
*
2
,
MAX_RECORDS
));
sprintf
(
record2
,
"%6d:%4d:%8d:XXX: %4d "
,
n1
,
n2
,
n3
,
update
);
make_record
(
record2
,
n1
,
n2
,
n3
,
"XXX"
,
update
);
if
(
rnd
(
2
)
==
1
)
if
(
rnd
(
2
)
==
1
)
{
{
if
(
heap_scan_init
(
file
))
if
(
heap_scan_init
(
file
))
...
@@ -654,3 +669,13 @@ static int calc_check(byte *buf, uint length)
...
@@ -654,3 +669,13 @@ static int calc_check(byte *buf, uint length)
check
+=
(
int
)
(
uchar
)
*
(
buf
++
);
check
+=
(
int
)
(
uchar
)
*
(
buf
++
);
return
check
;
return
check
;
}
}
static
void
make_record
(
char
*
record
,
uint
n1
,
uint
n2
,
uint
n3
,
const
char
*
mark
,
uint
count
)
{
bfill
(
record
,
reclength
,
' '
);
sprintf
(
record
,
"%6d:%4d:%8d:%3.3s: %4d"
,
n1
,
n2
,
n3
,
mark
,
count
);
record
[
37
]
=
'A'
;
/* Store A in null key */
record
[
38
]
=
1
;
/* set as null */
}
heap/hp_write.c
View file @
7dd4eb71
...
@@ -239,7 +239,9 @@ int _hp_write_key(register HP_SHARE *info, HP_KEYDEF *keyinfo,
...
@@ -239,7 +239,9 @@ int _hp_write_key(register HP_SHARE *info, HP_KEYDEF *keyinfo,
}
}
/* Check if dupplicated keys */
/* Check if dupplicated keys */
if
((
keyinfo
->
flag
&
HA_NOSAME
)
&&
pos
==
gpos
)
if
((
keyinfo
->
flag
&
HA_NOSAME
)
&&
pos
==
gpos
&&
(
!
(
keyinfo
->
flag
&
HA_NULL_PART_KEY
)
||
!
hp_if_null_in_key
(
keyinfo
,
record
)))
{
{
pos
=
empty
;
pos
=
empty
;
do
do
...
...
include/heap.h
View file @
7dd4eb71
...
@@ -78,11 +78,13 @@ typedef struct st_hp_keyseg /* Key-portion */
...
@@ -78,11 +78,13 @@ typedef struct st_hp_keyseg /* Key-portion */
uint
start
;
/* Start of key in record (from 0) */
uint
start
;
/* Start of key in record (from 0) */
uint
length
;
/* Keylength */
uint
length
;
/* Keylength */
uint
type
;
uint
type
;
uint
null_bit
;
/* bit set in row+null_pos */
uint
null_pos
;
}
HP_KEYSEG
;
}
HP_KEYSEG
;
typedef
struct
st_hp_keydef
/* Key definition with open */
typedef
struct
st_hp_keydef
/* Key definition with open */
{
{
uint
flag
;
/*
NOSAME
*/
uint
flag
;
/*
HA_NOSAME |HA_NULL_PART_KEY
*/
uint
keysegs
;
/* Number of key-segment */
uint
keysegs
;
/* Number of key-segment */
uint
length
;
/* Length of key (automatic) */
uint
length
;
/* Length of key (automatic) */
HP_KEYSEG
*
seg
;
HP_KEYSEG
*
seg
;
...
...
include/my_base.h
View file @
7dd4eb71
...
@@ -68,7 +68,8 @@ enum ha_rkey_function {
...
@@ -68,7 +68,8 @@ enum ha_rkey_function {
enum
ha_key_alg
{
enum
ha_key_alg
{
HA_KEY_ALG_BTREE
=
0
,
/* B-tree, default one */
HA_KEY_ALG_BTREE
=
0
,
/* B-tree, default one */
HA_KEY_ALG_RTREE
=
1
/* R-tree, for spatial searches */
HA_KEY_ALG_RTREE
=
1
,
/* R-tree, for spatial searches */
HA_KEY_ALG_HASH
=
2
/* HASH keys (HEAP tables) */
};
};
/* The following is parameter to ha_extra() */
/* The following is parameter to ha_extra() */
...
...
isam/static.c
View file @
7dd4eb71
...
@@ -15,7 +15,7 @@
...
@@ -15,7 +15,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/*
/*
Static variables for
pisam
library. All definied here for easy making of
Static variables for
ISAM
library. All definied here for easy making of
a shared library
a shared library
*/
*/
...
...
myisam/mi_static.c
View file @
7dd4eb71
...
@@ -15,7 +15,7 @@
...
@@ -15,7 +15,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/*
/*
Static variables for
pisam
library. All definied here for easy making of
Static variables for
MyISAM
library. All definied here for easy making of
a shared library
a shared library
*/
*/
...
...
sql/Makefile.am
View file @
7dd4eb71
...
@@ -51,7 +51,7 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
...
@@ -51,7 +51,7 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
sql_manager.h sql_map.h sql_string.h unireg.h
\
sql_manager.h sql_map.h sql_string.h unireg.h
\
field.h handler.h
\
field.h handler.h
\
ha_isammrg.h ha_isam.h ha_myisammrg.h
\
ha_isammrg.h ha_isam.h ha_myisammrg.h
\
ha_heap.h ha_myisam.h ha_berkeley.h ha_inno
base
.h
\
ha_heap.h ha_myisam.h ha_berkeley.h ha_inno
db
.h
\
opt_range.h opt_ft.h
\
opt_range.h opt_ft.h
\
sql_select.h structs.h table.h sql_udf.h hash_filo.h
\
sql_select.h structs.h table.h sql_udf.h hash_filo.h
\
lex.h lex_symbol.h sql_acl.h sql_crypt.h
\
lex.h lex_symbol.h sql_acl.h sql_crypt.h
\
...
@@ -74,7 +74,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \
...
@@ -74,7 +74,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \
time.cc opt_range.cc opt_sum.cc opt_ft.cc
\
time.cc opt_range.cc opt_sum.cc opt_ft.cc
\
records.cc filesort.cc handler.cc
\
records.cc filesort.cc handler.cc
\
ha_heap.cc ha_myisam.cc ha_myisammrg.cc
\
ha_heap.cc ha_myisam.cc ha_myisammrg.cc
\
ha_berkeley.cc ha_inno
base
.cc
\
ha_berkeley.cc ha_inno
db
.cc
\
ha_isam.cc ha_isammrg.cc
\
ha_isam.cc ha_isammrg.cc
\
sql_db.cc sql_table.cc sql_rename.cc sql_crypt.cc
\
sql_db.cc sql_table.cc sql_rename.cc sql_crypt.cc
\
sql_load.cc mf_iocache.cc field_conv.cc sql_show.cc
\
sql_load.cc mf_iocache.cc field_conv.cc sql_show.cc
\
...
...
sql/ha_berkeley.cc
View file @
7dd4eb71
...
@@ -1454,6 +1454,37 @@ int ha_berkeley::index_read(byte * buf, const byte * key,
...
@@ -1454,6 +1454,37 @@ int ha_berkeley::index_read(byte * buf, const byte * key,
DBUG_RETURN
(
error
);
DBUG_RETURN
(
error
);
}
}
/*
Read last key is solved by reading the next key and then reading
the previous key
*/
int
ha_berkeley
::
index_read_last
(
byte
*
buf
,
const
byte
*
key
,
uint
key_len
)
{
DBT
row
;
int
error
;
KEY
*
key_info
=
&
table
->
key_info
[
active_index
];
DBUG_ENTER
(
"ha_berkeley::index_read"
);
statistic_increment
(
ha_read_key_count
,
&
LOCK_status
);
bzero
((
char
*
)
&
row
,
sizeof
(
row
));
/* read of partial key */
pack_key
(
&
last_key
,
active_index
,
key_buff
,
key
,
key_len
);
/* Store for compare */
memcpy
(
key_buff2
,
key_buff
,
(
key_len
=
last_key
.
size
));
key_info
->
handler
.
bdb_return_if_eq
=
1
;
error
=
read_row
(
cursor
->
c_get
(
cursor
,
&
last_key
,
&
row
,
DB_SET_RANGE
),
(
char
*
)
buf
,
active_index
,
&
row
,
(
DBT
*
)
0
,
0
);
key_info
->
handler
.
bdb_return_if_eq
=
0
;
bzero
((
char
*
)
&
row
,
sizeof
(
row
));
if
(
read_row
(
cursor
->
c_get
(
cursor
,
&
last_key
,
&
row
,
DB_PREV
),
(
char
*
)
buf
,
active_index
,
&
row
,
&
last_key
,
1
)
||
berkeley_key_cmp
(
table
,
key_info
,
key_buff2
,
key_len
))
error
=
HA_ERR_KEY_NOT_FOUND
;
DBUG_RETURN
(
error
);
}
int
ha_berkeley
::
index_next
(
byte
*
buf
)
int
ha_berkeley
::
index_next
(
byte
*
buf
)
{
{
...
...
sql/ha_berkeley.h
View file @
7dd4eb71
...
@@ -89,7 +89,7 @@ class ha_berkeley: public handler
...
@@ -89,7 +89,7 @@ class ha_berkeley: public handler
int_option_flag
(
HA_READ_NEXT
|
HA_READ_PREV
|
int_option_flag
(
HA_READ_NEXT
|
HA_READ_PREV
|
HA_REC_NOT_IN_SEQ
|
HA_REC_NOT_IN_SEQ
|
HA_KEYPOS_TO_RNDPOS
|
HA_READ_ORDER
|
HA_LASTKEY_ORDER
|
HA_KEYPOS_TO_RNDPOS
|
HA_READ_ORDER
|
HA_LASTKEY_ORDER
|
HA_
LONGLONG_KEYS
|
HA_
NULL_KEY
|
HA_HAVE_KEY_READ_ONLY
|
HA_NULL_KEY
|
HA_HAVE_KEY_READ_ONLY
|
HA_BLOB_KEY
|
HA_NOT_EXACT_COUNT
|
HA_BLOB_KEY
|
HA_NOT_EXACT_COUNT
|
HA_PRIMARY_KEY_IN_READ_INDEX
|
HA_DROP_BEFORE_CREATE
|
HA_PRIMARY_KEY_IN_READ_INDEX
|
HA_DROP_BEFORE_CREATE
|
HA_AUTO_PART_KEY
),
HA_AUTO_PART_KEY
),
...
@@ -123,6 +123,7 @@ class ha_berkeley: public handler
...
@@ -123,6 +123,7 @@ class ha_berkeley: public handler
uint
key_len
,
enum
ha_rkey_function
find_flag
);
uint
key_len
,
enum
ha_rkey_function
find_flag
);
int
index_read_idx
(
byte
*
buf
,
uint
index
,
const
byte
*
key
,
int
index_read_idx
(
byte
*
buf
,
uint
index
,
const
byte
*
key
,
uint
key_len
,
enum
ha_rkey_function
find_flag
);
uint
key_len
,
enum
ha_rkey_function
find_flag
);
int
index_read_last
(
byte
*
buf
,
const
byte
*
key
,
uint
key_len
);
int
index_next
(
byte
*
buf
);
int
index_next
(
byte
*
buf
);
int
index_next_same
(
byte
*
buf
,
const
byte
*
key
,
uint
keylen
);
int
index_next_same
(
byte
*
buf
,
const
byte
*
key
,
uint
keylen
);
int
index_prev
(
byte
*
buf
);
int
index_prev
(
byte
*
buf
);
...
...
sql/ha_heap.cc
View file @
7dd4eb71
...
@@ -57,6 +57,7 @@ int ha_heap::open(const char *name, int mode, uint test_if_locked)
...
@@ -57,6 +57,7 @@ int ha_heap::open(const char *name, int mode, uint test_if_locked)
for
(
part
=
0
;
part
<
pos
->
key_parts
;
part
++
)
for
(
part
=
0
;
part
<
pos
->
key_parts
;
part
++
)
{
{
uint
flag
=
pos
->
key_part
[
part
].
key_type
;
uint
flag
=
pos
->
key_part
[
part
].
key_type
;
Field
*
field
=
pos
->
key_part
[
part
].
field
;
if
(
!
f_is_packed
(
flag
)
&&
if
(
!
f_is_packed
(
flag
)
&&
f_packtype
(
flag
)
==
(
int
)
FIELD_TYPE_DECIMAL
&&
f_packtype
(
flag
)
==
(
int
)
FIELD_TYPE_DECIMAL
&&
!
(
flag
&
FIELDFLAG_BINARY
))
!
(
flag
&
FIELDFLAG_BINARY
))
...
@@ -65,7 +66,17 @@ int ha_heap::open(const char *name, int mode, uint test_if_locked)
...
@@ -65,7 +66,17 @@ int ha_heap::open(const char *name, int mode, uint test_if_locked)
seg
->
type
=
(
int
)
HA_KEYTYPE_BINARY
;
seg
->
type
=
(
int
)
HA_KEYTYPE_BINARY
;
seg
->
start
=
(
uint
)
pos
->
key_part
[
part
].
offset
;
seg
->
start
=
(
uint
)
pos
->
key_part
[
part
].
offset
;
seg
->
length
=
(
uint
)
pos
->
key_part
[
part
].
length
;
seg
->
length
=
(
uint
)
pos
->
key_part
[
part
].
length
;
seg
++
;
if
(
field
->
null_ptr
)
{
seg
->
null_bit
=
field
->
null_bit
;
seg
->
null_pos
=
(
uint
)
(
field
->
null_ptr
-
(
uchar
*
)
table
->
record
[
0
]);
}
else
{
seg
->
null_bit
=
0
;
seg
->
null_pos
=
0
;
}
}
}
}
}
mem_per_row
+=
MY_ALIGN
(
table
->
reclength
+
1
,
sizeof
(
char
*
));
mem_per_row
+=
MY_ALIGN
(
table
->
reclength
+
1
,
sizeof
(
char
*
));
...
...
sql/ha_heap.h
View file @
7dd4eb71
...
@@ -36,7 +36,7 @@ class ha_heap: public handler
...
@@ -36,7 +36,7 @@ class ha_heap: public handler
ulong
option_flag
()
const
ulong
option_flag
()
const
{
return
(
HA_READ_RND_SAME
|
HA_NO_INDEX
|
HA_ONLY_WHOLE_INDEX
|
{
return
(
HA_READ_RND_SAME
|
HA_NO_INDEX
|
HA_ONLY_WHOLE_INDEX
|
HA_WRONG_ASCII_ORDER
|
HA_KEYPOS_TO_RNDPOS
|
HA_NO_BLOBS
|
HA_WRONG_ASCII_ORDER
|
HA_KEYPOS_TO_RNDPOS
|
HA_NO_BLOBS
|
HA_
REC_NOT_IN_SEQ
);
}
HA_
NULL_KEY
|
HA_REC_NOT_IN_SEQ
|
HA_NOT_READ_PREFIX_LAST
);
}
uint
max_record_length
()
const
{
return
HA_MAX_REC_LENGTH
;
}
uint
max_record_length
()
const
{
return
HA_MAX_REC_LENGTH
;
}
uint
max_keys
()
const
{
return
MAX_KEY
;
}
uint
max_keys
()
const
{
return
MAX_KEY
;
}
uint
max_key_parts
()
const
{
return
MAX_REF_PARTS
;
}
uint
max_key_parts
()
const
{
return
MAX_REF_PARTS
;
}
...
...
sql/ha_inno
base
.cc
→
sql/ha_inno
db
.cc
View file @
7dd4eb71
...
@@ -35,7 +35,7 @@ InnoDB */
...
@@ -35,7 +35,7 @@ InnoDB */
#define MAX_ULONG_BIT ((ulong) 1 << (sizeof(ulong)*8-1))
#define MAX_ULONG_BIT ((ulong) 1 << (sizeof(ulong)*8-1))
#include "ha_inno
base
.h"
#include "ha_inno
db
.h"
/* We must declare this here because we undef SAFE_MUTEX below */
/* We must declare this here because we undef SAFE_MUTEX below */
pthread_mutex_t
innobase_mutex
;
pthread_mutex_t
innobase_mutex
;
...
@@ -2008,6 +2008,24 @@ ha_innobase::index_read(
...
@@ -2008,6 +2008,24 @@ ha_innobase::index_read(
DBUG_RETURN
(
error
);
DBUG_RETURN
(
error
);
}
}
/*
The following functions works like index_read, but it find the last
row with the current index prefix.
This code is disabled until Heikki has verified that InnoDB support the
HA_READ_PREFIX_LAST flag and removed the HA_NOT_READ_PREFIX_LAST
flag from ha_innodb.h
*/
int
ha_innobase
::
index_read_last
(
mysql_byte
*
buf
,
const
mysql_byte
*
key_ptr
,
uint
key_len
)
{
return
index_read
(
buf
,
key_ptr
,
key_len
,
HA_READ_PREFIX_LAST
);
}
/************************************************************************
/************************************************************************
Changes the active index of a handle. */
Changes the active index of a handle. */
...
...
sql/ha_inno
base
.h
→
sql/ha_inno
db
.h
View file @
7dd4eb71
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
/* Copyright (C) 2000 MySQL AB && Innobase Oy
&& Innobase Oy
-This file is modified from ha_berkeley.h of MySQL distribution-
This program is free software; you can redistribute it and/or modify
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
it under the terms of the GNU General Public License as published by
...
@@ -17,13 +14,17 @@
...
@@ -17,13 +14,17 @@
along with this program; if not, write to the Free Software
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/*
This file is based on ha_berkeley.h of MySQL distribution
This file defines the Innodb handler: the interface between MySQL and
Innodb
*/
#ifdef __GNUC__
#ifdef __GNUC__
#pragma interface
/* gcc class implementation */
#pragma interface
/* gcc class implementation */
#endif
#endif
/* This file defines the Innobase handler: the interface between MySQL and
Innobase */
typedef
struct
st_innobase_share
{
typedef
struct
st_innobase_share
{
THR_LOCK
lock
;
THR_LOCK
lock
;
pthread_mutex_t
mutex
;
pthread_mutex_t
mutex
;
...
@@ -32,11 +33,11 @@ typedef struct st_innobase_share {
...
@@ -32,11 +33,11 @@ typedef struct st_innobase_share {
}
INNOBASE_SHARE
;
}
INNOBASE_SHARE
;
/* The class defining a handle to an Inno
base
table */
/* The class defining a handle to an Inno
db
table */
class
ha_innobase
:
public
handler
class
ha_innobase
:
public
handler
{
{
void
*
innobase_prebuilt
;
/* (row_prebuilt_t*) prebuilt
void
*
innobase_prebuilt
;
/* (row_prebuilt_t*) prebuilt
struct in Inno
base
, used to save
struct in Inno
db
, used to save
CPU */
CPU */
THD
*
user_thd
;
/* the thread handle of the user
THD
*
user_thd
;
/* the thread handle of the user
currently using the handle; this is
currently using the handle; this is
...
@@ -50,7 +51,7 @@ class ha_innobase: public handler
...
@@ -50,7 +51,7 @@ class ha_innobase: public handler
byte
*
upd_buff
;
/* buffer used in updates */
byte
*
upd_buff
;
/* buffer used in updates */
byte
*
key_val_buff
;
/* buffer used in converting
byte
*
key_val_buff
;
/* buffer used in converting
search key values from MySQL format
search key values from MySQL format
to Inno
base
format */
to Inno
db
format */
uint
ref_stored_len
;
/* length of the key value stored to
uint
ref_stored_len
;
/* length of the key value stored to
'ref' buffer of the handle, if any */
'ref' buffer of the handle, if any */
ulong
int_option_flag
;
ulong
int_option_flag
;
...
@@ -78,11 +79,11 @@ class ha_innobase: public handler
...
@@ -78,11 +79,11 @@ class ha_innobase: public handler
HA_REC_NOT_IN_SEQ
|
HA_REC_NOT_IN_SEQ
|
HA_KEYPOS_TO_RNDPOS
|
HA_LASTKEY_ORDER
|
HA_KEYPOS_TO_RNDPOS
|
HA_LASTKEY_ORDER
|
HA_HAVE_KEY_READ_ONLY
|
HA_READ_NOT_EXACT_KEY
|
HA_HAVE_KEY_READ_ONLY
|
HA_READ_NOT_EXACT_KEY
|
HA_
LONGLONG_KEYS
|
HA_
NULL_KEY
|
HA_NULL_KEY
|
HA_NOT_EXACT_COUNT
|
HA_NOT_EXACT_COUNT
|
HA_NO_WRITE_DELAYED
|
HA_NO_WRITE_DELAYED
|
HA_PRIMARY_KEY_IN_READ_INDEX
|
HA_PRIMARY_KEY_IN_READ_INDEX
|
HA_DROP_BEFORE_CREATE
|
HA_DROP_BEFORE_CREATE
|
HA_NOT_READ_PREFIX_LAST
|
HA_NO_PREFIX_CHAR_KEYS
),
HA_NO_PREFIX_CHAR_KEYS
),
last_dup_key
((
uint
)
-
1
),
last_dup_key
((
uint
)
-
1
),
start_of_scan
(
0
)
start_of_scan
(
0
)
...
@@ -125,6 +126,7 @@ class ha_innobase: public handler
...
@@ -125,6 +126,7 @@ class ha_innobase: public handler
uint
key_len
,
enum
ha_rkey_function
find_flag
);
uint
key_len
,
enum
ha_rkey_function
find_flag
);
int
index_read_idx
(
byte
*
buf
,
uint
index
,
const
byte
*
key
,
int
index_read_idx
(
byte
*
buf
,
uint
index
,
const
byte
*
key
,
uint
key_len
,
enum
ha_rkey_function
find_flag
);
uint
key_len
,
enum
ha_rkey_function
find_flag
);
int
index_read_last
(
byte
*
buf
,
const
byte
*
key
,
uint
key_len
);
int
index_next
(
byte
*
buf
);
int
index_next
(
byte
*
buf
);
int
index_next_same
(
byte
*
buf
,
const
byte
*
key
,
uint
keylen
);
int
index_next_same
(
byte
*
buf
,
const
byte
*
key
,
uint
keylen
);
int
index_prev
(
byte
*
buf
);
int
index_prev
(
byte
*
buf
);
...
...
sql/ha_isam.cc
View file @
7dd4eb71
...
@@ -109,6 +109,15 @@ int ha_isam::index_read_idx(byte * buf, uint index, const byte * key,
...
@@ -109,6 +109,15 @@ int ha_isam::index_read_idx(byte * buf, uint index, const byte * key,
return
!
error
?
0
:
my_errno
?
my_errno
:
-
1
;
return
!
error
?
0
:
my_errno
?
my_errno
:
-
1
;
}
}
int
ha_isam
::
index_read_last
(
byte
*
buf
,
const
byte
*
key
,
uint
key_len
)
{
statistic_increment
(
ha_read_key_count
,
&
LOCK_status
);
int
error
=
nisam_rkey
(
file
,
buf
,
active_index
,
key
,
key_len
,
HA_READ_PREFIX_LAST
);
table
->
status
=
error
?
STATUS_NOT_FOUND
:
0
;
return
!
error
?
0
:
my_errno
?
my_errno
:
-
1
;
}
int
ha_isam
::
index_next
(
byte
*
buf
)
int
ha_isam
::
index_next
(
byte
*
buf
)
{
{
statistic_increment
(
ha_read_next_count
,
&
LOCK_status
);
statistic_increment
(
ha_read_next_count
,
&
LOCK_status
);
...
...
sql/ha_isam.h
View file @
7dd4eb71
...
@@ -33,7 +33,7 @@ class ha_isam: public handler
...
@@ -33,7 +33,7 @@ class ha_isam: public handler
int_option_flag
(
HA_READ_NEXT
|
HA_READ_PREV
|
HA_READ_RND_SAME
|
int_option_flag
(
HA_READ_NEXT
|
HA_READ_PREV
|
HA_READ_RND_SAME
|
HA_KEYPOS_TO_RNDPOS
|
HA_READ_ORDER
|
HA_LASTKEY_ORDER
|
HA_KEYPOS_TO_RNDPOS
|
HA_READ_ORDER
|
HA_LASTKEY_ORDER
|
HA_HAVE_KEY_READ_ONLY
|
HA_READ_NOT_EXACT_KEY
|
HA_HAVE_KEY_READ_ONLY
|
HA_READ_NOT_EXACT_KEY
|
HA_
LONGLONG_KEYS
|
HA_
KEY_READ_WRONG_STR
|
HA_DUPP_POS
|
HA_KEY_READ_WRONG_STR
|
HA_DUPP_POS
|
HA_NOT_DELETE_WITH_CACHE
)
HA_NOT_DELETE_WITH_CACHE
)
{}
{}
~
ha_isam
()
{}
~
ha_isam
()
{}
...
@@ -57,6 +57,7 @@ class ha_isam: public handler
...
@@ -57,6 +57,7 @@ class ha_isam: public handler
uint
key_len
,
enum
ha_rkey_function
find_flag
);
uint
key_len
,
enum
ha_rkey_function
find_flag
);
int
index_read_idx
(
byte
*
buf
,
uint
idx
,
const
byte
*
key
,
int
index_read_idx
(
byte
*
buf
,
uint
idx
,
const
byte
*
key
,
uint
key_len
,
enum
ha_rkey_function
find_flag
);
uint
key_len
,
enum
ha_rkey_function
find_flag
);
int
index_read_last
(
byte
*
buf
,
const
byte
*
key
,
uint
key_len
);
int
index_next
(
byte
*
buf
);
int
index_next
(
byte
*
buf
);
int
index_prev
(
byte
*
buf
);
int
index_prev
(
byte
*
buf
);
int
index_first
(
byte
*
buf
);
int
index_first
(
byte
*
buf
);
...
...
sql/ha_isammrg.h
View file @
7dd4eb71
...
@@ -32,8 +32,9 @@ class ha_isammrg: public handler
...
@@ -32,8 +32,9 @@ class ha_isammrg: public handler
~
ha_isammrg
()
{}
~
ha_isammrg
()
{}
const
char
*
table_type
()
const
{
return
"MRG_ISAM"
;
}
const
char
*
table_type
()
const
{
return
"MRG_ISAM"
;
}
const
char
**
bas_ext
()
const
;
const
char
**
bas_ext
()
const
;
ulong
option_flag
()
const
{
return
HA_READ_RND_SAME
|
HA_KEYPOS_TO_RNDPOS
ulong
option_flag
()
const
{
return
(
HA_READ_RND_SAME
|
HA_KEYPOS_TO_RNDPOS
|
|
HA_REC_NOT_IN_SEQ
;}
HA_NOT_READ_PREFIX_LAST
|
HA_REC_NOT_IN_SEQ
);
}
uint
max_record_length
()
const
{
return
HA_MAX_REC_LENGTH
;
}
uint
max_record_length
()
const
{
return
HA_MAX_REC_LENGTH
;
}
uint
max_keys
()
const
{
return
0
;
}
uint
max_keys
()
const
{
return
0
;
}
uint
max_key_parts
()
const
{
return
0
;
}
uint
max_key_parts
()
const
{
return
0
;
}
...
...
sql/ha_myisam.cc
View file @
7dd4eb71
...
@@ -777,6 +777,14 @@ int ha_myisam::index_read_idx(byte * buf, uint index, const byte * key,
...
@@ -777,6 +777,14 @@ int ha_myisam::index_read_idx(byte * buf, uint index, const byte * key,
return
error
;
return
error
;
}
}
int
ha_myisam
::
index_read_last
(
byte
*
buf
,
const
byte
*
key
,
uint
key_len
)
{
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
;
}
int
ha_myisam
::
index_next
(
byte
*
buf
)
int
ha_myisam
::
index_next
(
byte
*
buf
)
{
{
statistic_increment
(
ha_read_next_count
,
&
LOCK_status
);
statistic_increment
(
ha_read_next_count
,
&
LOCK_status
);
...
@@ -973,7 +981,7 @@ void ha_myisam::update_create_info(HA_CREATE_INFO *create_info)
...
@@ -973,7 +981,7 @@ void ha_myisam::update_create_info(HA_CREATE_INFO *create_info)
}
}
int
ha_myisam
::
create
(
const
char
*
name
,
register
TABLE
*
form
,
int
ha_myisam
::
create
(
const
char
*
name
,
register
TABLE
*
table
,
HA_CREATE_INFO
*
info
)
HA_CREATE_INFO
*
info
)
{
{
int
error
;
int
error
;
...
@@ -985,20 +993,20 @@ int ha_myisam::create(const char *name, register TABLE *form,
...
@@ -985,20 +993,20 @@ int ha_myisam::create(const char *name, register TABLE *form,
MI_KEYDEF
*
keydef
;
MI_KEYDEF
*
keydef
;
MI_COLUMNDEF
*
recinfo
,
*
recinfo_pos
;
MI_COLUMNDEF
*
recinfo
,
*
recinfo_pos
;
MI_KEYSEG
*
keyseg
;
MI_KEYSEG
*
keyseg
;
uint
options
=
form
->
db_options_in_use
;
uint
options
=
table
->
db_options_in_use
;
DBUG_ENTER
(
"ha_myisam::create"
);
DBUG_ENTER
(
"ha_myisam::create"
);
type
=
HA_KEYTYPE_BINARY
;
// Keep compiler happy
type
=
HA_KEYTYPE_BINARY
;
// Keep compiler happy
if
(
!
(
my_multi_malloc
(
MYF
(
MY_WME
),
if
(
!
(
my_multi_malloc
(
MYF
(
MY_WME
),
&
recinfo
,(
form
->
fields
*
2
+
2
)
*
sizeof
(
MI_COLUMNDEF
),
&
recinfo
,(
table
->
fields
*
2
+
2
)
*
sizeof
(
MI_COLUMNDEF
),
&
keydef
,
form
->
keys
*
sizeof
(
MI_KEYDEF
),
&
keydef
,
table
->
keys
*
sizeof
(
MI_KEYDEF
),
&
keyseg
,
&
keyseg
,
((
form
->
key_parts
+
form
->
keys
)
*
sizeof
(
MI_KEYSEG
)),
((
table
->
key_parts
+
table
->
keys
)
*
sizeof
(
MI_KEYSEG
)),
0
)))
0
)))
DBUG_RETURN
(
1
);
DBUG_RETURN
(
1
);
pos
=
form
->
key_info
;
pos
=
table
->
key_info
;
for
(
i
=
0
;
i
<
form
->
keys
;
i
++
,
pos
++
)
for
(
i
=
0
;
i
<
table
->
keys
;
i
++
,
pos
++
)
{
{
keydef
[
i
].
flag
=
(
pos
->
flags
&
(
HA_NOSAME
|
HA_FULLTEXT
));
keydef
[
i
].
flag
=
(
pos
->
flags
&
(
HA_NOSAME
|
HA_FULLTEXT
));
keydef
[
i
].
seg
=
keyseg
;
keydef
[
i
].
seg
=
keyseg
;
...
@@ -1041,7 +1049,7 @@ int ha_myisam::create(const char *name, register TABLE *form,
...
@@ -1041,7 +1049,7 @@ int ha_myisam::create(const char *name, register TABLE *form,
{
{
keydef
[
i
].
seg
[
j
].
null_bit
=
field
->
null_bit
;
keydef
[
i
].
seg
[
j
].
null_bit
=
field
->
null_bit
;
keydef
[
i
].
seg
[
j
].
null_pos
=
(
uint
)
(
field
->
null_ptr
-
keydef
[
i
].
seg
[
j
].
null_pos
=
(
uint
)
(
field
->
null_ptr
-
(
uchar
*
)
form
->
record
[
0
]);
(
uchar
*
)
table
->
record
[
0
]);
}
}
else
else
{
{
...
@@ -1059,19 +1067,19 @@ int ha_myisam::create(const char *name, register TABLE *form,
...
@@ -1059,19 +1067,19 @@ int ha_myisam::create(const char *name, register TABLE *form,
keydef
[
i
].
seg
[
j
].
flag
|=
HA_BLOB_PART
;
keydef
[
i
].
seg
[
j
].
flag
|=
HA_BLOB_PART
;
/* save number of bytes used to pack length */
/* save number of bytes used to pack length */
keydef
[
i
].
seg
[
j
].
bit_start
=
(
uint
)
(
field
->
pack_length
()
-
keydef
[
i
].
seg
[
j
].
bit_start
=
(
uint
)
(
field
->
pack_length
()
-
form
->
blob_ptr_size
);
table
->
blob_ptr_size
);
}
}
}
}
keyseg
+=
pos
->
key_parts
;
keyseg
+=
pos
->
key_parts
;
}
}
recpos
=
0
;
recinfo_pos
=
recinfo
;
recpos
=
0
;
recinfo_pos
=
recinfo
;
while
(
recpos
<
(
uint
)
form
->
reclength
)
while
(
recpos
<
(
uint
)
table
->
reclength
)
{
{
Field
**
field
,
*
found
=
0
;
Field
**
field
,
*
found
=
0
;
minpos
=
form
->
reclength
;
length
=
0
;
minpos
=
table
->
reclength
;
length
=
0
;
for
(
field
=
form
->
field
;
*
field
;
field
++
)
for
(
field
=
table
->
field
;
*
field
;
field
++
)
{
{
if
((
fieldpos
=
(
*
field
)
->
offset
())
>=
recpos
&&
if
((
fieldpos
=
(
*
field
)
->
offset
())
>=
recpos
&&
fieldpos
<=
minpos
)
fieldpos
<=
minpos
)
...
@@ -1117,7 +1125,7 @@ int ha_myisam::create(const char *name, register TABLE *form,
...
@@ -1117,7 +1125,7 @@ int ha_myisam::create(const char *name, register TABLE *form,
{
{
recinfo_pos
->
null_bit
=
found
->
null_bit
;
recinfo_pos
->
null_bit
=
found
->
null_bit
;
recinfo_pos
->
null_pos
=
(
uint
)
(
found
->
null_ptr
-
recinfo_pos
->
null_pos
=
(
uint
)
(
found
->
null_ptr
-
(
uchar
*
)
form
->
record
[
0
]);
(
uchar
*
)
table
->
record
[
0
]);
}
}
else
else
{
{
...
@@ -1132,20 +1140,23 @@ int ha_myisam::create(const char *name, register TABLE *form,
...
@@ -1132,20 +1140,23 @@ int ha_myisam::create(const char *name, register TABLE *form,
}
}
MI_CREATE_INFO
create_info
;
MI_CREATE_INFO
create_info
;
bzero
((
char
*
)
&
create_info
,
sizeof
(
create_info
));
bzero
((
char
*
)
&
create_info
,
sizeof
(
create_info
));
create_info
.
max_rows
=
form
->
max_rows
;
create_info
.
max_rows
=
table
->
max_rows
;
create_info
.
reloc_rows
=
form
->
min_rows
;
create_info
.
reloc_rows
=
table
->
min_rows
;
create_info
.
auto_increment
=
(
info
->
auto_increment_value
?
create_info
.
auto_increment
=
(
info
->
auto_increment_value
?
info
->
auto_increment_value
-
1
:
info
->
auto_increment_value
-
1
:
(
ulonglong
)
0
);
(
ulonglong
)
0
);
create_info
.
data_file_length
=
(
ulonglong
)
form
->
max_rows
*
form
->
avg_row_length
;
create_info
.
data_file_length
=
((
ulonglong
)
table
->
max_rows
*
table
->
avg_row_length
);
create_info
.
raid_type
=
info
->
raid_type
;
create_info
.
raid_type
=
info
->
raid_type
;
create_info
.
raid_chunks
=
info
->
raid_chunks
?
info
->
raid_chunks
:
RAID_DEFAULT_CHUNKS
;
create_info
.
raid_chunks
=
(
info
->
raid_chunks
?
info
->
raid_chunks
:
create_info
.
raid_chunksize
=
info
->
raid_chunksize
?
info
->
raid_chunksize
:
RAID_DEFAULT_CHUNKSIZE
;
RAID_DEFAULT_CHUNKS
);
create_info
.
raid_chunksize
=
(
info
->
raid_chunksize
?
info
->
raid_chunksize
:
RAID_DEFAULT_CHUNKSIZE
);
create_info
.
data_file_name
=
info
->
data_file_name
;
create_info
.
data_file_name
=
info
->
data_file_name
;
create_info
.
index_file_name
=
info
->
index_file_name
;
create_info
.
index_file_name
=
info
->
index_file_name
;
error
=
mi_create
(
fn_format
(
buff
,
name
,
""
,
""
,
2
+
4
),
error
=
mi_create
(
fn_format
(
buff
,
name
,
""
,
""
,
2
+
4
),
form
->
keys
,
keydef
,
table
->
keys
,
keydef
,
(
uint
)
(
recinfo_pos
-
recinfo
),
recinfo
,
(
uint
)
(
recinfo_pos
-
recinfo
),
recinfo
,
0
,
(
MI_UNIQUEDEF
*
)
0
,
0
,
(
MI_UNIQUEDEF
*
)
0
,
&
create_info
,
&
create_info
,
...
...
sql/ha_myisam.h
View file @
7dd4eb71
...
@@ -47,7 +47,7 @@ class ha_myisam: public handler
...
@@ -47,7 +47,7 @@ class ha_myisam: public handler
int_option_flag
(
HA_READ_NEXT
|
HA_READ_PREV
|
HA_READ_RND_SAME
|
int_option_flag
(
HA_READ_NEXT
|
HA_READ_PREV
|
HA_READ_RND_SAME
|
HA_KEYPOS_TO_RNDPOS
|
HA_READ_ORDER
|
HA_LASTKEY_ORDER
|
HA_KEYPOS_TO_RNDPOS
|
HA_READ_ORDER
|
HA_LASTKEY_ORDER
|
HA_HAVE_KEY_READ_ONLY
|
HA_READ_NOT_EXACT_KEY
|
HA_HAVE_KEY_READ_ONLY
|
HA_READ_NOT_EXACT_KEY
|
HA_
LONGLONG_KEYS
|
HA_
NULL_KEY
|
HA_NULL_KEY
|
HA_CAN_FULLTEXT
|
HA_CAN_SQL_HANDLER
|
HA_CAN_FULLTEXT
|
HA_CAN_SQL_HANDLER
|
HA_DUPP_POS
|
HA_BLOB_KEY
|
HA_AUTO_PART_KEY
),
HA_DUPP_POS
|
HA_BLOB_KEY
|
HA_AUTO_PART_KEY
),
enable_activate_all_index
(
1
)
enable_activate_all_index
(
1
)
...
@@ -71,6 +71,7 @@ class ha_myisam: public handler
...
@@ -71,6 +71,7 @@ class ha_myisam: public handler
uint
key_len
,
enum
ha_rkey_function
find_flag
);
uint
key_len
,
enum
ha_rkey_function
find_flag
);
int
index_read_idx
(
byte
*
buf
,
uint
idx
,
const
byte
*
key
,
int
index_read_idx
(
byte
*
buf
,
uint
idx
,
const
byte
*
key
,
uint
key_len
,
enum
ha_rkey_function
find_flag
);
uint
key_len
,
enum
ha_rkey_function
find_flag
);
int
index_read_last
(
byte
*
buf
,
const
byte
*
key
,
uint
key_len
);
int
index_next
(
byte
*
buf
);
int
index_next
(
byte
*
buf
);
int
index_prev
(
byte
*
buf
);
int
index_prev
(
byte
*
buf
);
int
index_first
(
byte
*
buf
);
int
index_first
(
byte
*
buf
);
...
@@ -78,8 +79,14 @@ class ha_myisam: public handler
...
@@ -78,8 +79,14 @@ class ha_myisam: public handler
int
index_next_same
(
byte
*
buf
,
const
byte
*
key
,
uint
keylen
);
int
index_next_same
(
byte
*
buf
,
const
byte
*
key
,
uint
keylen
);
int
index_end
()
{
ft_handler
=
NULL
;
return
0
;
}
int
index_end
()
{
ft_handler
=
NULL
;
return
0
;
}
int
ft_init
()
int
ft_init
()
{
if
(
!
ft_handler
)
return
1
;
ft_handler
->
please
->
reinit_search
(
ft_handler
);
return
0
;
}
{
FT_INFO
*
ft_init_ext
(
uint
mode
,
uint
inx
,
const
byte
*
key
,
uint
keylen
,
bool
presort
)
if
(
!
ft_handler
)
return
1
;
ft_handler
->
please
->
reinit_search
(
ft_handler
);
return
0
;
}
FT_INFO
*
ft_init_ext
(
uint
mode
,
uint
inx
,
const
byte
*
key
,
uint
keylen
,
bool
presort
)
{
return
ft_init_search
(
mode
,
file
,
inx
,(
byte
*
)
key
,
keylen
,
presort
);
}
{
return
ft_init_search
(
mode
,
file
,
inx
,(
byte
*
)
key
,
keylen
,
presort
);
}
int
ft_read
(
byte
*
buf
);
int
ft_read
(
byte
*
buf
);
int
rnd_init
(
bool
scan
=
1
);
int
rnd_init
(
bool
scan
=
1
);
...
...
sql/ha_myisammrg.cc
View file @
7dd4eb71
...
@@ -112,6 +112,15 @@ int ha_myisammrg::index_read_idx(byte * buf, uint index, const byte * key,
...
@@ -112,6 +112,15 @@ int ha_myisammrg::index_read_idx(byte * buf, uint index, const byte * key,
return
error
;
return
error
;
}
}
int
ha_myisammrg
::
index_read_last
(
byte
*
buf
,
const
byte
*
key
,
uint
key_len
)
{
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
;
}
int
ha_myisammrg
::
index_next
(
byte
*
buf
)
int
ha_myisammrg
::
index_next
(
byte
*
buf
)
{
{
statistic_increment
(
ha_read_next_count
,
&
LOCK_status
);
statistic_increment
(
ha_read_next_count
,
&
LOCK_status
);
...
...
sql/ha_myisammrg.h
View file @
7dd4eb71
...
@@ -38,7 +38,7 @@ class ha_myisammrg: public handler
...
@@ -38,7 +38,7 @@ class ha_myisammrg: public handler
HA_HAVE_KEY_READ_ONLY
|
HA_HAVE_KEY_READ_ONLY
|
HA_KEYPOS_TO_RNDPOS
|
HA_READ_ORDER
|
HA_KEYPOS_TO_RNDPOS
|
HA_READ_ORDER
|
HA_LASTKEY_ORDER
|
HA_READ_NOT_EXACT_KEY
|
HA_LASTKEY_ORDER
|
HA_READ_NOT_EXACT_KEY
|
HA_
LONGLONG_KEYS
|
HA_
NULL_KEY
|
HA_BLOB_KEY
);
}
HA_NULL_KEY
|
HA_BLOB_KEY
);
}
uint
max_record_length
()
const
{
return
HA_MAX_REC_LENGTH
;
}
uint
max_record_length
()
const
{
return
HA_MAX_REC_LENGTH
;
}
uint
max_keys
()
const
{
return
MI_MAX_KEY
;
}
uint
max_keys
()
const
{
return
MI_MAX_KEY
;
}
uint
max_key_parts
()
const
{
return
MAX_REF_PARTS
;
}
uint
max_key_parts
()
const
{
return
MAX_REF_PARTS
;
}
...
@@ -55,6 +55,7 @@ class ha_myisammrg: public handler
...
@@ -55,6 +55,7 @@ class ha_myisammrg: public handler
uint
key_len
,
enum
ha_rkey_function
find_flag
);
uint
key_len
,
enum
ha_rkey_function
find_flag
);
int
index_read_idx
(
byte
*
buf
,
uint
idx
,
const
byte
*
key
,
int
index_read_idx
(
byte
*
buf
,
uint
idx
,
const
byte
*
key
,
uint
key_len
,
enum
ha_rkey_function
find_flag
);
uint
key_len
,
enum
ha_rkey_function
find_flag
);
int
index_read_last
(
byte
*
buf
,
const
byte
*
key
,
uint
key_len
);
int
index_next
(
byte
*
buf
);
int
index_next
(
byte
*
buf
);
int
index_prev
(
byte
*
buf
);
int
index_prev
(
byte
*
buf
);
int
index_first
(
byte
*
buf
);
int
index_first
(
byte
*
buf
);
...
...
sql/handler.cc
View file @
7dd4eb71
...
@@ -33,7 +33,7 @@
...
@@ -33,7 +33,7 @@
#include "ha_berkeley.h"
#include "ha_berkeley.h"
#endif
#endif
#ifdef HAVE_INNOBASE_DB
#ifdef HAVE_INNOBASE_DB
#include "ha_inno
base
.h"
#include "ha_inno
db
.h"
#endif
#endif
#include <myisampack.h>
#include <myisampack.h>
#include <errno.h>
#include <errno.h>
...
...
sql/handler.h
View file @
7dd4eb71
...
@@ -55,12 +55,11 @@
...
@@ -55,12 +55,11 @@
#define HA_REC_NOT_IN_SEQ 64
/* ha_info don't return recnumber;
#define HA_REC_NOT_IN_SEQ 64
/* ha_info don't return recnumber;
It returns a position to ha_r_rnd */
It returns a position to ha_r_rnd */
#define HA_ONLY_WHOLE_INDEX 128
/* Can't use part key searches */
#define HA_ONLY_WHOLE_INDEX 128
/* Can't use part key searches */
#define HA_
RSAME_NO_INDEX
256
/* RSAME can't restore index */
#define HA_
NOT_READ_PREFIX_LAST
256
/* RSAME can't restore index */
#define HA_WRONG_ASCII_ORDER 512
/* Can't use sorting through key */
#define HA_WRONG_ASCII_ORDER 512
/* Can't use sorting through key */
#define HA_HAVE_KEY_READ_ONLY 1024
/* Can read only keys (no record) */
#define HA_HAVE_KEY_READ_ONLY 1024
/* Can read only keys (no record) */
#define HA_READ_NOT_EXACT_KEY 2048
/* Can read record after/before key */
#define HA_READ_NOT_EXACT_KEY 2048
/* Can read record after/before key */
#define HA_NO_INDEX 4096
/* No index needed for next/prev */
#define HA_NO_INDEX 4096
/* No index needed for next/prev */
#define HA_LONGLONG_KEYS 8192
/* Can have longlong as key */
#define HA_KEY_READ_WRONG_STR 16384
/* keyread returns converted strings */
#define HA_KEY_READ_WRONG_STR 16384
/* keyread returns converted strings */
#define HA_NULL_KEY 32768
/* One can have keys with NULL */
#define HA_NULL_KEY 32768
/* One can have keys with NULL */
#define HA_DUPP_POS 65536
/* ha_position() gives dupp row */
#define HA_DUPP_POS 65536
/* ha_position() gives dupp row */
...
@@ -256,6 +255,10 @@ public:
...
@@ -256,6 +255,10 @@ public:
virtual
int
index_first
(
byte
*
buf
)
=
0
;
virtual
int
index_first
(
byte
*
buf
)
=
0
;
virtual
int
index_last
(
byte
*
buf
)
=
0
;
virtual
int
index_last
(
byte
*
buf
)
=
0
;
virtual
int
index_next_same
(
byte
*
buf
,
const
byte
*
key
,
uint
keylen
);
virtual
int
index_next_same
(
byte
*
buf
,
const
byte
*
key
,
uint
keylen
);
virtual
int
index_read_last
(
byte
*
buf
,
const
byte
*
key
,
uint
key_len
)
{
return
(
my_errno
=
HA_ERR_WRONG_COMMAND
);
}
virtual
int
ft_init
()
virtual
int
ft_init
()
{
return
-
1
;
}
{
return
-
1
;
}
virtual
FT_INFO
*
ft_init_ext
(
uint
mode
,
uint
inx
,
const
byte
*
key
,
uint
keylen
,
virtual
FT_INFO
*
ft_init_ext
(
uint
mode
,
uint
inx
,
const
byte
*
key
,
uint
keylen
,
...
...
sql/mysqld.cc
View file @
7dd4eb71
...
@@ -27,7 +27,7 @@
...
@@ -27,7 +27,7 @@
#include "ha_berkeley.h"
#include "ha_berkeley.h"
#endif
#endif
#ifdef HAVE_INNOBASE_DB
#ifdef HAVE_INNOBASE_DB
#include "ha_inno
base
.h"
#include "ha_inno
db
.h"
#endif
#endif
#include "ha_myisam.h"
#include "ha_myisam.h"
#include <nisam.h>
#include <nisam.h>
...
...
sql/sql_delete.cc
View file @
7dd4eb71
...
@@ -24,7 +24,7 @@
...
@@ -24,7 +24,7 @@
#include "mysql_priv.h"
#include "mysql_priv.h"
#include "ha_inno
base
.h"
#include "ha_inno
db
.h"
#include "sql_select.h"
#include "sql_select.h"
int
mysql_delete
(
THD
*
thd
,
TABLE_LIST
*
table_list
,
COND
*
conds
,
ORDER
*
order
,
int
mysql_delete
(
THD
*
thd
,
TABLE_LIST
*
table_list
,
COND
*
conds
,
ORDER
*
order
,
...
...
sql/sql_select.cc
View file @
7dd4eb71
...
@@ -89,15 +89,18 @@ static int join_read_system(JOIN_TAB *tab);
...
@@ -89,15 +89,18 @@ static int join_read_system(JOIN_TAB *tab);
static
int
join_read_const
(
JOIN_TAB
*
tab
);
static
int
join_read_const
(
JOIN_TAB
*
tab
);
static
int
join_read_key
(
JOIN_TAB
*
tab
);
static
int
join_read_key
(
JOIN_TAB
*
tab
);
static
int
join_read_always_key
(
JOIN_TAB
*
tab
);
static
int
join_read_always_key
(
JOIN_TAB
*
tab
);
static
int
join_read_last_key
(
JOIN_TAB
*
tab
);
static
int
join_no_more_records
(
READ_RECORD
*
info
);
static
int
join_no_more_records
(
READ_RECORD
*
info
);
static
int
join_read_next
(
READ_RECORD
*
info
);
static
int
join_read_next
(
READ_RECORD
*
info
);
static
int
join_init_quick_read_record
(
JOIN_TAB
*
tab
);
static
int
join_init_quick_read_record
(
JOIN_TAB
*
tab
);
static
int
test_if_quick_select
(
JOIN_TAB
*
tab
);
static
int
test_if_quick_select
(
JOIN_TAB
*
tab
);
static
int
join_init_read_record
(
JOIN_TAB
*
tab
);
static
int
join_init_read_record
(
JOIN_TAB
*
tab
);
static
int
join_init_read_first_with_key
(
JOIN_TAB
*
tab
);
static
int
join_read_first
(
JOIN_TAB
*
tab
);
static
int
join_init_read_next_with_key
(
READ_RECORD
*
info
);
static
int
join_read_next
(
READ_RECORD
*
info
);
static
int
join_init_read_last_with_key
(
JOIN_TAB
*
tab
);
static
int
join_read_next_same
(
READ_RECORD
*
info
);
static
int
join_init_read_prev_with_key
(
READ_RECORD
*
info
);
static
int
join_read_last
(
JOIN_TAB
*
tab
);
static
int
join_read_prev_same
(
READ_RECORD
*
info
);
static
int
join_read_prev
(
READ_RECORD
*
info
);
static
int
join_ft_read_first
(
JOIN_TAB
*
tab
);
static
int
join_ft_read_first
(
JOIN_TAB
*
tab
);
static
int
join_ft_read_next
(
READ_RECORD
*
info
);
static
int
join_ft_read_next
(
READ_RECORD
*
info
);
static
COND
*
make_cond_for_table
(
COND
*
cond
,
table_map
table
,
static
COND
*
make_cond_for_table
(
COND
*
cond
,
table_map
table
,
...
@@ -2510,7 +2513,7 @@ make_join_readinfo(JOIN *join,uint options)
...
@@ -2510,7 +2513,7 @@ make_join_readinfo(JOIN *join,uint options)
tab
->
quick
=
0
;
tab
->
quick
=
0
;
table
->
file
->
index_init
(
tab
->
ref
.
key
);
table
->
file
->
index_init
(
tab
->
ref
.
key
);
tab
->
read_first_record
=
join_read_always_key
;
tab
->
read_first_record
=
join_read_always_key
;
tab
->
read_record
.
read_record
=
join_read_next
;
tab
->
read_record
.
read_record
=
join_read_next
_same
;
if
(
table
->
used_keys
&
((
key_map
)
1
<<
tab
->
ref
.
key
)
&&
if
(
table
->
used_keys
&
((
key_map
)
1
<<
tab
->
ref
.
key
)
&&
!
table
->
no_keyread
)
!
table
->
no_keyread
)
{
{
...
@@ -2585,7 +2588,7 @@ make_join_readinfo(JOIN *join,uint options)
...
@@ -2585,7 +2588,7 @@ make_join_readinfo(JOIN *join,uint options)
{
// Only read index tree
{
// Only read index tree
tab
->
index
=
find_shortest_key
(
table
,
table
->
used_keys
);
tab
->
index
=
find_shortest_key
(
table
,
table
->
used_keys
);
tab
->
table
->
file
->
index_init
(
tab
->
index
);
tab
->
table
->
file
->
index_init
(
tab
->
index
);
tab
->
read_first_record
=
join_
init_read_first_with_key
;
tab
->
read_first_record
=
join_
read_first
;
tab
->
type
=
JT_NEXT
;
// Read with index_first / index_next
tab
->
type
=
JT_NEXT
;
// Read with index_first / index_next
}
}
}
}
...
@@ -3641,6 +3644,10 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
...
@@ -3641,6 +3644,10 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
{
{
if
(
field
->
flags
&
GROUP_FLAG
&&
!
using_unique_constraint
)
if
(
field
->
flags
&
GROUP_FLAG
&&
!
using_unique_constraint
)
{
{
/*
We have to reserve one byte here for NULL bits,
as this is updated by 'end_update()'
*/
*
pos
++=
0
;
// Null is stored here
*
pos
++=
0
;
// Null is stored here
recinfo
->
length
=
1
;
recinfo
->
length
=
1
;
recinfo
->
type
=
FIELD_NORMAL
;
recinfo
->
type
=
FIELD_NORMAL
;
...
@@ -3730,11 +3737,11 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
...
@@ -3730,11 +3737,11 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
{
{
/*
/*
To be able to group on NULL, we move the null bit to be
To be able to group on NULL, we move the null bit to be
just before the column and extend the key to cover the null bit
just before the column.
The null byte is updated by 'end_update()'
*/
*/
*
group_buff
=
0
;
// Init null byte
key_part_info
->
null_bit
=
1
;
key_part_info
->
offset
--
;
key_part_info
->
null_offset
=
key_part_info
->
offset
-
1
;
key_part_info
->
length
++
;
group
->
field
->
move_field
((
char
*
)
group_buff
+
1
,
(
uchar
*
)
group_buff
,
group
->
field
->
move_field
((
char
*
)
group_buff
+
1
,
(
uchar
*
)
group_buff
,
1
);
1
);
}
}
...
@@ -4497,6 +4504,35 @@ join_read_always_key(JOIN_TAB *tab)
...
@@ -4497,6 +4504,35 @@ join_read_always_key(JOIN_TAB *tab)
return
0
;
return
0
;
}
}
/*
This function is used when optimizing away ORDER BY in
SELECT * FROM t1 WHERE a=1 ORDER BY a DESC,b DESC
*/
static
int
join_read_last_key
(
JOIN_TAB
*
tab
)
{
int
error
;
TABLE
*
table
=
tab
->
table
;
if
(
cp_buffer_from_ref
(
&
tab
->
ref
))
return
-
1
;
if
((
error
=
table
->
file
->
index_read_last
(
table
->
record
[
0
],
tab
->
ref
.
key_buff
,
tab
->
ref
.
key_length
)))
{
if
(
error
!=
HA_ERR_KEY_NOT_FOUND
)
{
sql_print_error
(
"read_const: Got error %d when reading table %s"
,
error
,
table
->
path
);
table
->
file
->
print_error
(
error
,
MYF
(
0
));
return
1
;
}
return
-
1
;
/* purecov: inspected */
}
return
0
;
}
/* ARGSUSED */
/* ARGSUSED */
static
int
static
int
...
@@ -4507,7 +4543,7 @@ join_no_more_records(READ_RECORD *info __attribute__((unused)))
...
@@ -4507,7 +4543,7 @@ join_no_more_records(READ_RECORD *info __attribute__((unused)))
static
int
static
int
join_read_next
(
READ_RECORD
*
info
)
join_read_next
_same
(
READ_RECORD
*
info
)
{
{
int
error
;
int
error
;
TABLE
*
table
=
info
->
table
;
TABLE
*
table
=
info
->
table
;
...
@@ -4530,6 +4566,37 @@ join_read_next(READ_RECORD *info)
...
@@ -4530,6 +4566,37 @@ join_read_next(READ_RECORD *info)
return
0
;
return
0
;
}
}
static
int
join_read_prev_same
(
READ_RECORD
*
info
)
{
int
error
;
TABLE
*
table
=
info
->
table
;
JOIN_TAB
*
tab
=
table
->
reginfo
.
join_tab
;
if
((
error
=
table
->
file
->
index_prev
(
table
->
record
[
0
])))
{
if
(
error
!=
HA_ERR_END_OF_FILE
)
{
sql_print_error
(
"read_next: Got error %d when reading table %s"
,
error
,
table
->
path
);
table
->
file
->
print_error
(
error
,
MYF
(
0
));
error
=
1
;
}
else
{
table
->
status
=
STATUS_GARBAGE
;
error
=
-
1
;
}
}
else
if
(
key_cmp
(
table
,
tab
->
ref
.
key_buff
,
tab
->
ref
.
key
,
tab
->
ref
.
key_length
))
{
table
->
status
=
STATUS_NOT_FOUND
;
error
=
1
;
}
return
error
;
}
static
int
static
int
join_init_quick_read_record
(
JOIN_TAB
*
tab
)
join_init_quick_read_record
(
JOIN_TAB
*
tab
)
...
@@ -4560,7 +4627,7 @@ join_init_read_record(JOIN_TAB *tab)
...
@@ -4560,7 +4627,7 @@ join_init_read_record(JOIN_TAB *tab)
}
}
static
int
static
int
join_
init_read_first_with_key
(
JOIN_TAB
*
tab
)
join_
read_first
(
JOIN_TAB
*
tab
)
{
{
int
error
;
int
error
;
TABLE
*
table
=
tab
->
table
;
TABLE
*
table
=
tab
->
table
;
...
@@ -4571,7 +4638,7 @@ join_init_read_first_with_key(JOIN_TAB *tab)
...
@@ -4571,7 +4638,7 @@ join_init_read_first_with_key(JOIN_TAB *tab)
table
->
file
->
extra
(
HA_EXTRA_KEYREAD
);
table
->
file
->
extra
(
HA_EXTRA_KEYREAD
);
}
}
tab
->
table
->
status
=
0
;
tab
->
table
->
status
=
0
;
tab
->
read_record
.
read_record
=
join_
init_read_next_with_key
;
tab
->
read_record
.
read_record
=
join_
read_next
;
tab
->
read_record
.
table
=
table
;
tab
->
read_record
.
table
=
table
;
tab
->
read_record
.
file
=
table
->
file
;
tab
->
read_record
.
file
=
table
->
file
;
tab
->
read_record
.
index
=
tab
->
index
;
tab
->
read_record
.
index
=
tab
->
index
;
...
@@ -4591,8 +4658,9 @@ join_init_read_first_with_key(JOIN_TAB *tab)
...
@@ -4591,8 +4658,9 @@ join_init_read_first_with_key(JOIN_TAB *tab)
return
0
;
return
0
;
}
}
static
int
static
int
join_
init_read_next_with_key
(
READ_RECORD
*
info
)
join_
read_next
(
READ_RECORD
*
info
)
{
{
int
error
=
info
->
file
->
index_next
(
info
->
record
);
int
error
=
info
->
file
->
index_next
(
info
->
record
);
if
(
error
)
if
(
error
)
...
@@ -4609,9 +4677,8 @@ join_init_read_next_with_key(READ_RECORD *info)
...
@@ -4609,9 +4677,8 @@ join_init_read_next_with_key(READ_RECORD *info)
return
0
;
return
0
;
}
}
static
int
static
int
join_
init_read_last_with_key
(
JOIN_TAB
*
tab
)
join_
read_last
(
JOIN_TAB
*
tab
)
{
{
TABLE
*
table
=
tab
->
table
;
TABLE
*
table
=
tab
->
table
;
int
error
;
int
error
;
...
@@ -4621,7 +4688,7 @@ join_init_read_last_with_key(JOIN_TAB *tab)
...
@@ -4621,7 +4688,7 @@ join_init_read_last_with_key(JOIN_TAB *tab)
table
->
file
->
extra
(
HA_EXTRA_KEYREAD
);
table
->
file
->
extra
(
HA_EXTRA_KEYREAD
);
}
}
tab
->
table
->
status
=
0
;
tab
->
table
->
status
=
0
;
tab
->
read_record
.
read_record
=
join_
init_read_prev_with_key
;
tab
->
read_record
.
read_record
=
join_
read_prev
;
tab
->
read_record
.
table
=
table
;
tab
->
read_record
.
table
=
table
;
tab
->
read_record
.
file
=
table
->
file
;
tab
->
read_record
.
file
=
table
->
file
;
tab
->
read_record
.
index
=
tab
->
index
;
tab
->
read_record
.
index
=
tab
->
index
;
...
@@ -4641,8 +4708,9 @@ join_init_read_last_with_key(JOIN_TAB *tab)
...
@@ -4641,8 +4708,9 @@ join_init_read_last_with_key(JOIN_TAB *tab)
return
0
;
return
0
;
}
}
static
int
static
int
join_
init_read_prev_with_key
(
READ_RECORD
*
info
)
join_
read_prev
(
READ_RECORD
*
info
)
{
{
int
error
=
info
->
file
->
index_prev
(
info
->
record
);
int
error
=
info
->
file
->
index_prev
(
info
->
record
);
if
(
error
)
if
(
error
)
...
@@ -4659,6 +4727,7 @@ join_init_read_prev_with_key(READ_RECORD *info)
...
@@ -4659,6 +4727,7 @@ join_init_read_prev_with_key(READ_RECORD *info)
return
0
;
return
0
;
}
}
static
int
static
int
join_ft_read_first
(
JOIN_TAB
*
tab
)
join_ft_read_first
(
JOIN_TAB
*
tab
)
{
{
...
@@ -4734,7 +4803,8 @@ end_send(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
...
@@ -4734,7 +4803,8 @@ end_send(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
if
(
join
->
select_options
&
OPTION_FOUND_ROWS
)
if
(
join
->
select_options
&
OPTION_FOUND_ROWS
)
{
{
JOIN_TAB
*
jt
=
join
->
join_tab
;
JOIN_TAB
*
jt
=
join
->
join_tab
;
if
((
join
->
tables
==
1
)
&&
!
join
->
tmp_table
&&
!
join
->
sort_and_group
&&
!
join
->
send_group_parts
&&
!
join
->
having
&&
!
jt
->
select_cond
)
if
((
join
->
tables
==
1
)
&&
!
join
->
tmp_table
&&
!
join
->
sort_and_group
&&
!
join
->
send_group_parts
&&
!
join
->
having
&&
!
jt
->
select_cond
)
{
{
join
->
select_options
^=
OPTION_FOUND_ROWS
;
join
->
select_options
^=
OPTION_FOUND_ROWS
;
join
->
send_records
=
jt
->
records
;
join
->
send_records
=
jt
->
records
;
...
@@ -5315,6 +5385,9 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
...
@@ -5315,6 +5385,9 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
if
(
ref_key
>=
0
)
if
(
ref_key
>=
0
)
{
{
/*
We come here when there is a REF key.
*/
int
order_direction
;
int
order_direction
;
uint
used_key_parts
;
uint
used_key_parts
;
/* 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 */
...
@@ -5322,11 +5395,11 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
...
@@ -5322,11 +5395,11 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
(
order_direction
=
test_if_order_by_key
(
order
,
table
,
ref_key
,
(
order_direction
=
test_if_order_by_key
(
order
,
table
,
ref_key
,
&
used_key_parts
)))
&
used_key_parts
)))
{
{
if
(
order_direction
==
-
1
)
if
(
order_direction
==
-
1
)
// If ORDER BY ... DESC
{
{
if
(
select
&&
select
->
quick
)
if
(
select
&&
select
->
quick
)
{
{
// ORDER BY r
ef
_key DESC
// ORDER BY r
ange
_key DESC
QUICK_SELECT_DESC
*
tmp
=
new
QUICK_SELECT_DESC
(
select
->
quick
,
QUICK_SELECT_DESC
*
tmp
=
new
QUICK_SELECT_DESC
(
select
->
quick
,
used_key_parts
);
used_key_parts
);
if
(
!
tmp
||
tmp
->
error
)
if
(
!
tmp
||
tmp
->
error
)
...
@@ -5341,11 +5414,15 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
...
@@ -5341,11 +5414,15 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
{
{
/*
/*
SELECT * FROM t1 WHERE a=1 ORDER BY a DESC,b DESC
SELECT * FROM t1 WHERE a=1 ORDER BY a DESC,b DESC
TODO:
Add a new traversal function to read last matching row and
Use a traversal function that starts by reading the last row
traverse
backwards.
with key part (A) and then traverse the index
backwards.
*/
*/
DBUG_RETURN
(
0
);
if
(
table
->
file
->
option_flag
()
&
HA_NOT_READ_PREFIX_LAST
)
DBUG_RETURN
(
1
);
tab
->
read_first_record
=
join_read_last_key
;
tab
->
read_record
.
read_record
=
join_read_prev_same
;
/* fall through */
}
}
}
}
DBUG_RETURN
(
1
);
/* No need to sort */
DBUG_RETURN
(
1
);
/* No need to sort */
...
@@ -5377,8 +5454,8 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
...
@@ -5377,8 +5454,8 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
if
(
!
no_changes
)
if
(
!
no_changes
)
{
{
tab
->
index
=
nr
;
tab
->
index
=
nr
;
tab
->
read_first_record
=
(
flag
>
0
?
join_
init_read_first_with_key
:
tab
->
read_first_record
=
(
flag
>
0
?
join_
read_first
:
join_
init_read_last_with_key
);
join_
read_last
);
table
->
file
->
index_init
(
nr
);
table
->
file
->
index_init
(
nr
);
tab
->
type
=
JT_NEXT
;
// Read with index_first(), index_next()
tab
->
type
=
JT_NEXT
;
// Read with index_first(), index_next()
if
(
table
->
used_keys
&
((
key_map
)
1
<<
nr
))
if
(
table
->
used_keys
&
((
key_map
)
1
<<
nr
))
...
@@ -6369,7 +6446,8 @@ get_sort_by_table(ORDER *a,ORDER *b,TABLE_LIST *tables)
...
@@ -6369,7 +6446,8 @@ get_sort_by_table(ORDER *a,ORDER *b,TABLE_LIST *tables)
static
void
static
void
calc_group_buffer
(
JOIN
*
join
,
ORDER
*
group
)
calc_group_buffer
(
JOIN
*
join
,
ORDER
*
group
)
{
{
uint
key_length
=
0
,
parts
=
0
;
uint
key_length
=
0
,
parts
=
0
,
null_parts
=
0
;
if
(
group
)
if
(
group
)
join
->
group
=
1
;
join
->
group
=
1
;
for
(;
group
;
group
=
group
->
next
)
for
(;
group
;
group
=
group
->
next
)
...
@@ -6390,10 +6468,11 @@ calc_group_buffer(JOIN *join,ORDER *group)
...
@@ -6390,10 +6468,11 @@ calc_group_buffer(JOIN *join,ORDER *group)
key_length
+=
(
*
group
->
item
)
->
max_length
;
key_length
+=
(
*
group
->
item
)
->
max_length
;
parts
++
;
parts
++
;
if
((
*
group
->
item
)
->
maybe_null
)
if
((
*
group
->
item
)
->
maybe_null
)
key_length
++
;
null_parts
++
;
}
}
join
->
tmp_table_param
.
group_length
=
key_length
;
join
->
tmp_table_param
.
group_length
=
key_length
+
null_parts
;
join
->
tmp_table_param
.
group_parts
=
parts
;
join
->
tmp_table_param
.
group_parts
=
parts
;
join
->
tmp_table_param
.
group_null_parts
=
null_parts
;
}
}
...
...
sql/sql_select.h
View file @
7dd4eb71
...
@@ -127,12 +127,13 @@ class TMP_TABLE_PARAM {
...
@@ -127,12 +127,13 @@ class TMP_TABLE_PARAM {
ha_rows
end_write_records
;
ha_rows
end_write_records
;
uint
field_count
,
sum_func_count
,
func_count
;
uint
field_count
,
sum_func_count
,
func_count
;
uint
hidden_field_count
;
uint
hidden_field_count
;
uint
group_parts
,
group_length
;
uint
group_parts
,
group_length
,
group_null_parts
;
uint
quick_group
;
uint
quick_group
;
bool
using_indirect_summary_function
;
bool
using_indirect_summary_function
;
TMP_TABLE_PARAM
()
TMP_TABLE_PARAM
()
:
copy_funcs_it
(
copy_funcs
),
copy_field
(
0
),
group_parts
(
0
),
group_length
(
0
)
:
copy_funcs_it
(
copy_funcs
),
copy_field
(
0
),
group_parts
(
0
),
group_length
(
0
),
group_null_parts
(
0
)
{}
{}
~
TMP_TABLE_PARAM
()
~
TMP_TABLE_PARAM
()
{
{
...
...
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