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
6e17f4f2
Commit
6e17f4f2
authored
Oct 24, 2003
by
serg@serg.mylan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fixes to Bitmap class
parent
d74ecc07
Changes
15
Show whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
236 additions
and
245 deletions
+236
-245
include/my_bitmap.h
include/my_bitmap.h
+3
-4
mysql-test/r/range.result
mysql-test/r/range.result
+4
-4
mysys/my_bitmap.c
mysys/my_bitmap.c
+78
-97
sql/field.cc
sql/field.cc
+2
-1
sql/field.h
sql/field.h
+3
-3
sql/ha_berkeley.h
sql/ha_berkeley.h
+1
-1
sql/ha_innodb.h
sql/ha_innodb.h
+1
-1
sql/ha_myisam.cc
sql/ha_myisam.cc
+2
-1
sql/handler.h
sql/handler.h
+1
-1
sql/mysql_priv.h
sql/mysql_priv.h
+1
-101
sql/opt_range.cc
sql/opt_range.cc
+11
-10
sql/opt_range.h
sql/opt_range.h
+1
-1
sql/sql_bitmap.h
sql/sql_bitmap.h
+108
-0
sql/sql_select.cc
sql/sql_select.cc
+17
-17
sql/table.cc
sql/table.cc
+3
-3
No files found.
include/my_bitmap.h
View file @
6e17f4f2
...
...
@@ -25,14 +25,13 @@ typedef struct st_bitmap
{
uchar
*
bitmap
;
uint
bitmap_size
;
my_bool
thread_safe
;
/* set if several threads access the bitmap */
/*
mutex will be acquired for the duration of each bitmap operation if
thread_safe flag i
s set. Otherwise, we optimize by not acquiring the
mutex
thread_safe flag i
n bitmap_init was set. Otherwise, we optimize by not
acquiring the
mutex
*/
#ifdef THREAD
pthread_mutex_t
mutex
;
pthread_mutex_t
*
mutex
;
#endif
}
MY_BITMAP
;
...
...
mysql-test/r/range.result
View file @
6e17f4f2
...
...
@@ -240,11 +240,11 @@ id select_type table type possible_keys key key_len ref rows Extra
explain select * from t1, t1 t2 where t1.y = 2 and t2.x between t1.y-1 and t1.y+1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref y y 5 const 1 Using where
1 SIMPLE t2 ALL x NULL NULL NULL 9 Range checked for each record (index map: 1)
1 SIMPLE t2 ALL x NULL NULL NULL 9 Range checked for each record (index map:
0x
1)
explain select * from t1, t1 t2 where t1.y = 2 and t2.x >= t1.y-1 and t2.x <= t1.y+1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref y y 5 const 1 Using where
1 SIMPLE t2 ALL x NULL NULL NULL 9 Range checked for each record (index map: 1)
1 SIMPLE t2 ALL x NULL NULL NULL 9 Range checked for each record (index map:
0x
1)
explain select * from t1, t1 t2 where t1.y = 2 and t2.x between 0 and t1.y;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref y y 5 const 1 Using where
...
...
@@ -267,11 +267,11 @@ INSERT INTO t2 VALUES (0),(0),(1),(1),(2),(2);
explain select * from t1, t2 where (t1.key1 <t2.keya + 1) and t2.keya=3;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ref j1 j1 4 const 1 Using where; Using index
1 SIMPLE t1 ALL i1,i2 NULL NULL NULL 4 Range checked for each record (index map: 3)
1 SIMPLE t1 ALL i1,i2 NULL NULL NULL 4 Range checked for each record (index map:
0x
3)
explain select * from t1 force index(i2), t2 where (t1.key1 <t2.keya + 1) and t2.keya=3;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ref j1 j1 4 const 1 Using where; Using index
1 SIMPLE t1 ALL i2 NULL NULL NULL 4 Range checked for each record (index map: 2)
1 SIMPLE t1 ALL i2 NULL NULL NULL 4 Range checked for each record (index map:
0x
2)
DROP TABLE t1,t2;
create table t1 (id int(10) primary key);
insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9);
...
...
mysys/my_bitmap.c
View file @
6e17f4f2
...
...
@@ -30,63 +30,67 @@
inline
void
bitmap_lock
(
MY_BITMAP
*
map
)
{
#ifdef THREAD
if
(
map
->
thread_safe
)
pthread_mutex_lock
(
&
map
->
mutex
);
if
(
map
->
mutex
)
pthread_mutex_lock
(
map
->
mutex
);
#endif
}
inline
void
bitmap_unlock
(
MY_BITMAP
*
map
)
{
#ifdef THREAD
if
(
map
->
thread_safe
)
pthread_mutex_unlock
(
&
map
->
mutex
);
if
(
map
->
mutex
)
pthread_mutex_unlock
(
map
->
mutex
);
#endif
}
my_bool
bitmap_init
(
MY_BITMAP
*
map
,
uchar
*
buf
,
uint
bitmap_size
,
my_bool
thread_safe
)
{
// for efficiency reasons - MY_BITMAP is heavily used
DBUG_ASSERT
((
bitmap_size
&
7
)
==
0
);
bitmap_size
/=
8
;
if
(
!
(
map
->
bitmap
=
buf
)
&&
!
(
map
->
bitmap
=
(
uchar
*
)
my_malloc
((
bitmap_size
+
7
)
/
8
,
!
(
map
->
bitmap
=
(
uchar
*
)
my_malloc
(
bitmap_size
+
sizeof
(
pthread_mutex_t
)
,
MYF
(
MY_WME
|
MY_ZEROFILL
))))
return
1
;
DBUG_ASSERT
(
bitmap_size
!=
~
(
uint
)
0
)
;
map
->
bitmap_size
=
bitmap_size
;
#ifdef THREAD
if
((
map
->
thread_safe
=
thread_safe
))
pthread_mutex_init
(
&
map
->
mutex
,
MY_MUTEX_INIT_FAST
);
if
(
thread_safe
)
{
map
->
mutex
=
(
pthread_mutex_t
*
)(
map
->
bitmap
+
bitmap_size
);
pthread_mutex_init
(
map
->
mutex
,
MY_MUTEX_INIT_FAST
);
}
else
map
->
mutex
=
0
;
#endif
map
->
bitmap_size
=
bitmap_size
;
return
0
;
}
void
bitmap_free
(
MY_BITMAP
*
map
)
{
#ifdef THREAD
if
(
map
->
mutex
)
pthread_mutex_destroy
(
map
->
mutex
);
#endif
if
(
map
->
bitmap
)
{
my_free
((
char
*
)
map
->
bitmap
,
MYF
(
0
));
map
->
bitmap
=
0
;
#ifdef THREAD
if
(
map
->
thread_safe
)
pthread_mutex_destroy
(
&
map
->
mutex
);
#endif
}
}
void
bitmap_set_bit
(
MY_BITMAP
*
map
,
uint
bitmap_bit
)
{
DBUG_ASSERT
(
map
->
bitmap
);
if
(
bitmap_bit
<
map
->
bitmap_size
)
{
DBUG_ASSERT
(
map
->
bitmap
&&
bitmap_bit
<
map
->
bitmap_size
*
8
);
bitmap_lock
(
map
);
map
->
bitmap
[
bitmap_bit
/
8
]
|=
(
1
<<
(
bitmap_bit
&
7
));
bitmap_unlock
(
map
);
}
}
uint
bitmap_set_next
(
MY_BITMAP
*
map
)
{
uchar
*
bitmap
=
map
->
bitmap
;
uint
bit_found
=
MY_BIT_NONE
;
uint
bitmap_size
=
map
->
bitmap_size
;
uint
bitmap_size
=
map
->
bitmap_size
*
8
;
uint
i
;
DBUG_ASSERT
(
map
->
bitmap
);
...
...
@@ -114,28 +118,25 @@ uint bitmap_set_next(MY_BITMAP *map)
void
bitmap_clear_bit
(
MY_BITMAP
*
map
,
uint
bitmap_bit
)
{
DBUG_ASSERT
(
map
->
bitmap
);
if
(
bitmap_bit
<
map
->
bitmap_size
)
{
DBUG_ASSERT
(
map
->
bitmap
&&
bitmap_bit
<
map
->
bitmap_size
*
8
);
bitmap_lock
(
map
);
map
->
bitmap
[
bitmap_bit
/
8
]
&=
~
(
1
<<
(
bitmap_bit
&
7
));
bitmap_unlock
(
map
);
}
}
void
bitmap_set_prefix
(
MY_BITMAP
*
map
,
uint
prefix_size
)
{
uint
l
,
m
;
uint
prefix_bytes
,
prefix_bits
;
DBUG_ASSERT
(
map
->
bitmap
);
bitmap_lock
(
map
);
set_if_smaller
(
prefix_size
,
map
->
bitmap_size
);
if
((
l
=
prefix_size
/
8
))
memset
(
map
->
bitmap
,
0xff
,
l
);
if
((
m
=
prefix_size
&
7
))
map
->
bitmap
[
l
++
]
=
(
1
<<
m
)
-
1
;
if
(
l
<
(
m
=
(
map
->
bitmap_size
+
7
)
/
8
)
)
bzero
(
map
->
bitmap
+
l
,
m
-
l
);
set_if_smaller
(
prefix_size
,
map
->
bitmap_size
*
8
);
if
((
prefix_bytes
=
prefix_size
/
8
))
memset
(
map
->
bitmap
,
0xff
,
prefix_bytes
);
if
((
prefix_bits
=
prefix_size
&
7
))
map
->
bitmap
[
prefix_bytes
++
]
=
(
1
<<
prefix_bits
)
-
1
;
if
(
prefix_bytes
<
map
->
bitmap_size
)
bzero
(
map
->
bitmap
+
prefix_bytes
,
map
->
bitmap_size
-
prefix_bytes
);
bitmap_unlock
(
map
);
}
...
...
@@ -146,27 +147,27 @@ void bitmap_clear_all(MY_BITMAP *map)
void
bitmap_set_all
(
MY_BITMAP
*
map
)
{
bitmap_set_prefix
(
map
,
map
->
bitmap_size
);
bitmap_set_prefix
(
map
,
~
0
);
}
my_bool
bitmap_is_prefix
(
MY_BITMAP
*
map
,
uint
prefix_size
)
{
uint
l
=
prefix_size
/
8
,
m
=
prefix_size
&
7
,
i
,
res
=
0
;
uint
prefix_bits
=
prefix_size
&
7
,
res
=
0
;
uchar
*
m
=
map
->
bitmap
,
*
end_prefix
=
map
->
bitmap
+
prefix_size
/
8
,
*
end
=
map
->
bitmap
+
map
->
bitmap_size
;
DBUG_ASSERT
(
map
->
bitmap
);
if
(
prefix_size
>
map
->
bitmap_size
)
return
0
;
DBUG_ASSERT
(
map
->
bitmap
&&
prefix_size
<=
map
->
bitmap_size
*
8
);
bitmap_lock
(
map
);
for
(
i
=
0
;
i
<
l
;
i
++
)
if
(
map
->
bitmap
[
i
]
!=
0xff
)
while
(
m
<
end_prefix
)
if
(
*
m
++
!=
0xff
)
goto
ret
;
if
(
m
&&
map
->
bitmap
[
i
++
]
!=
(
1
<<
m
)
-
1
)
if
(
prefix_bits
&&
*
m
++
!=
(
1
<<
prefix_bits
)
-
1
)
goto
ret
;
for
(
m
=
(
map
->
bitmap_size
+
7
)
/
8
;
i
<
m
;
i
++
)
if
(
m
ap
->
bitmap
[
i
]
!=
0
)
while
(
m
<
end
)
if
(
m
++
!=
0
)
goto
ret
;
res
=
1
;
...
...
@@ -182,38 +183,31 @@ my_bool bitmap_is_clear_all(MY_BITMAP *map)
my_bool
bitmap_is_set_all
(
MY_BITMAP
*
map
)
{
return
bitmap_is_prefix
(
map
,
map
->
bitmap_size
);
return
bitmap_is_prefix
(
map
,
map
->
bitmap_size
*
8
);
}
my_bool
bitmap_is_set
(
MY_BITMAP
*
map
,
uint
bitmap_bit
)
{
DBUG_ASSERT
(
map
->
bitmap
);
return
(
bitmap_bit
<
map
->
bitmap_size
)
?
(
map
->
bitmap
[
bitmap_bit
/
8
]
&
(
1
<<
(
bitmap_bit
&
7
)))
:
0
;
DBUG_ASSERT
(
map
->
bitmap
&&
bitmap_bit
<
map
->
bitmap_size
*
8
);
return
map
->
bitmap
[
bitmap_bit
/
8
]
&
(
1
<<
(
bitmap_bit
&
7
));
}
my_bool
bitmap_is_subset
(
MY_BITMAP
*
map1
,
MY_BITMAP
*
map2
)
{
uint
l
1
,
l2
,
i
,
res
=
0
;
uchar
*
m1
=
map1
->
bitmap
,
*
m2
=
map2
->
bitmap
;
uint
l
ength
,
res
=
0
;
uchar
*
m1
=
map1
->
bitmap
,
*
m2
=
map2
->
bitmap
,
*
end
;
DBUG_ASSERT
(
map1
->
bitmap
);
DBUG_ASSERT
(
map2
->
bitmap
);
DBUG_ASSERT
(
map1
->
bitmap
&&
map2
->
bitmap
&&
map1
->
bitmap_size
==
map2
->
bitmap_size
);
bitmap_lock
(
map1
);
bitmap_lock
(
map2
);
l1
=
(
map1
->
bitmap_size
+
7
)
/
8
;
l2
=
(
map2
->
bitmap_size
+
7
)
/
8
;
set_if_smaller
(
l2
,
l1
);
end
=
m1
+
map1
->
bitmap_size
;
for
(
i
=
0
;
i
<
l2
;
i
++
)
while
(
m1
<
end
)
if
((
*
m1
++
)
&
~
(
*
m2
++
))
goto
ret
;
for
(;
i
<
l1
;
i
++
)
if
(
*
m1
++
)
goto
ret
;
res
=
1
;
ret:
bitmap_unlock
(
map2
);
...
...
@@ -225,13 +219,12 @@ my_bool bitmap_cmp(MY_BITMAP *map1, MY_BITMAP *map2)
{
uint
res
;
DBUG_ASSERT
(
map1
->
bitmap
);
DBUG_ASSERT
(
map2
->
bitmap
);
DBUG_ASSERT
(
map1
->
bitmap
&&
map2
->
bitmap
&&
map1
->
bitmap_size
==
map2
->
bitmap_size
);
bitmap_lock
(
map1
);
bitmap_lock
(
map2
);
res
=
map1
->
bitmap_size
==
map2
->
bitmap_size
&&
memcmp
(
map1
->
bitmap
,
map2
->
bitmap
,
(
map1
->
bitmap_size
+
7
)
/
8
)
==
0
;
res
=
memcmp
(
map1
->
bitmap
,
map2
->
bitmap
,
map1
->
bitmap_size
)
==
0
;
bitmap_unlock
(
map2
);
bitmap_unlock
(
map1
);
...
...
@@ -240,23 +233,17 @@ my_bool bitmap_cmp(MY_BITMAP *map1, MY_BITMAP *map2)
void
bitmap_intersect
(
MY_BITMAP
*
map
,
MY_BITMAP
*
map2
)
{
uint
l1
,
l2
,
i
;
uchar
*
m
=
map
->
bitmap
,
*
m2
=
map2
->
bitmap
;
uchar
*
to
=
map
->
bitmap
,
*
from
=
map2
->
bitmap
,
*
end
;
DBUG_ASSERT
(
map
->
bitmap
);
DBUG_ASSERT
(
map2
->
bitmap
);
DBUG_ASSERT
(
map
->
bitmap
&&
map2
->
bitmap
&&
map
->
bitmap_size
==
map2
->
bitmap_size
);
bitmap_lock
(
map
);
bitmap_lock
(
map2
);
l1
=
(
map
->
bitmap_size
+
7
)
/
8
;
l2
=
(
map2
->
bitmap_size
+
7
)
/
8
;
set_if_smaller
(
l2
,
l1
);
for
(
i
=
0
;
i
<
l2
;
i
++
)
*
m
++
&=
*
m2
++
;
end
=
to
+
map
->
bitmap_size
;
if
(
l1
>
l2
)
bzero
(
m
,
l1
-
l2
)
;
while
(
to
<
end
)
*
to
++
&=
*
from
++
;
bitmap_unlock
(
map2
);
bitmap_unlock
(
map
);
...
...
@@ -264,20 +251,17 @@ void bitmap_intersect(MY_BITMAP *map, MY_BITMAP *map2)
void
bitmap_subtract
(
MY_BITMAP
*
map
,
MY_BITMAP
*
map2
)
{
uint
l1
,
l2
,
i
;
uchar
*
m
=
map
->
bitmap
,
*
m2
=
map2
->
bitmap
;
uchar
*
to
=
map
->
bitmap
,
*
from
=
map2
->
bitmap
,
*
end
;
DBUG_ASSERT
(
map
->
bitmap
);
DBUG_ASSERT
(
map2
->
bitmap
);
DBUG_ASSERT
(
map
->
bitmap
&&
map2
->
bitmap
&&
map
->
bitmap_size
==
map2
->
bitmap_size
);
bitmap_lock
(
map
);
bitmap_lock
(
map2
);
l1
=
(
map
->
bitmap_size
+
7
)
/
8
;
l2
=
(
map2
->
bitmap_size
+
7
)
/
8
;
set_if_smaller
(
l2
,
l1
);
end
=
to
+
map
->
bitmap_size
;
for
(
i
=
0
;
i
<
l2
;
i
++
)
*
m
++
&=
~
(
*
m2
++
);
while
(
to
<
end
)
*
to
++
&=
~
(
*
from
++
);
bitmap_unlock
(
map2
);
bitmap_unlock
(
map
);
...
...
@@ -285,20 +269,17 @@ void bitmap_subtract(MY_BITMAP *map, MY_BITMAP *map2)
void
bitmap_union
(
MY_BITMAP
*
map
,
MY_BITMAP
*
map2
)
{
uint
l1
,
l2
,
i
;
uchar
*
m
=
map
->
bitmap
,
*
m2
=
map2
->
bitmap
;
uchar
*
to
=
map
->
bitmap
,
*
from
=
map2
->
bitmap
,
*
end
;
DBUG_ASSERT
(
map
->
bitmap
);
DBUG_ASSERT
(
map2
->
bitmap
);
DBUG_ASSERT
(
map
->
bitmap
&&
map2
->
bitmap
&&
map
->
bitmap_size
==
map2
->
bitmap_size
);
bitmap_lock
(
map
);
bitmap_lock
(
map2
);
l1
=
(
map
->
bitmap_size
+
7
)
/
8
;
l2
=
(
map2
->
bitmap_size
+
7
)
/
8
;
set_if_smaller
(
l2
,
l1
);
end
=
to
+
map
->
bitmap_size
;
for
(
i
=
0
;
i
<
l2
;
i
++
)
*
m
++
|=
*
m2
++
;
while
(
to
<
end
)
*
to
++
|=
*
from
++
;
bitmap_unlock
(
map2
);
bitmap_unlock
(
map
);
...
...
sql/field.cc
View file @
6e17f4f2
...
...
@@ -181,7 +181,8 @@ Field::Field(char *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,
:
ptr
(
ptr_arg
),
null_ptr
(
null_ptr_arg
),
table
(
table_arg
),
table_name
(
table_arg
?
table_arg
->
table_name
:
0
),
field_name
(
field_name_arg
),
query_id
(
0
),
unireg_check
(
unireg_check_arg
),
query_id
(
0
),
key_start
(
0
),
part_of_key
(
0
),
part_of_sortkey
(
0
),
unireg_check
(
unireg_check_arg
),
field_length
(
length_arg
),
null_bit
(
null_bit_arg
),
abs_offset
(
0
)
{
flags
=
null_ptr
?
0
:
NOT_NULL_FLAG
;
...
...
sql/field.h
View file @
6e17f4f2
...
...
@@ -151,9 +151,9 @@ class Field
if
(
tmp
->
table
->
maybe_null
)
tmp
->
flags
&=
~
NOT_NULL_FLAG
;
tmp
->
table
=
new_table
;
tmp
->
key_start
.
init
(
).
clear_all
(
);
tmp
->
part_of_key
.
init
(
).
clear_all
(
);
tmp
->
part_of_sortkey
.
init
(
).
clear_all
(
);
tmp
->
key_start
.
init
(
0
);
tmp
->
part_of_key
.
init
(
0
);
tmp
->
part_of_sortkey
.
init
(
0
);
tmp
->
unireg_check
=
Field
::
NONE
;
tmp
->
flags
&=
(
NOT_NULL_FLAG
|
BLOB_FLAG
|
UNSIGNED_FLAG
|
ZEROFILL_FLAG
|
BINARY_FLAG
|
ENUM_FLAG
|
SET_FLAG
);
...
...
sql/ha_berkeley.h
View file @
6e17f4f2
...
...
@@ -107,7 +107,7 @@ class ha_berkeley: public handler
uint
extra_rec_buf_length
()
{
return
BDB_HIDDEN_PRIMARY_KEY_LENGTH
;
}
ha_rows
estimate_number_of_rows
();
bool
fast_key_read
()
{
return
1
;}
const
key_map
&
keys_to_use_for_scanning
()
{
return
key_map_full
;
}
const
key_map
*
keys_to_use_for_scanning
()
{
return
&
key_map_full
;
}
bool
has_transactions
()
{
return
1
;}
int
open
(
const
char
*
name
,
int
mode
,
uint
test_if_locked
);
...
...
sql/ha_innodb.h
View file @
6e17f4f2
...
...
@@ -125,7 +125,7 @@ class ha_innobase: public handler
uint
max_key_length
()
const
{
return
((
MAX_KEY_LENGTH
<=
3500
)
?
MAX_KEY_LENGTH
:
3500
);}
bool
fast_key_read
()
{
return
1
;}
const
key_map
&
keys_to_use_for_scanning
()
{
return
key_map_full
;
}
const
key_map
*
keys_to_use_for_scanning
()
{
return
&
key_map_full
;
}
bool
has_transactions
()
{
return
1
;}
int
open
(
const
char
*
name
,
int
mode
,
uint
test_if_locked
);
...
...
sql/ha_myisam.cc
View file @
6e17f4f2
...
...
@@ -1023,7 +1023,8 @@ void ha_myisam::info(uint flag)
ref_length
=
info
.
reflength
;
table
->
db_options_in_use
=
info
.
options
;
block_size
=
myisam_block_size
;
table
->
keys_in_use
.
set_prefix
(
table
->
keys
).
intersect
(
info
.
key_map
);
table
->
keys_in_use
.
set_prefix
(
table
->
keys
);
table
->
keys_in_use
.
intersect
(
info
.
key_map
);
table
->
keys_for_keyread
=
table
->
keys_in_use
;
table
->
keys_for_keyread
.
subtract
(
table
->
read_only_keys
);
table
->
db_record_offset
=
info
.
record_offset
;
...
...
sql/handler.h
View file @
6e17f4f2
...
...
@@ -241,7 +241,7 @@ class handler :public Sql_alloc
virtual
double
read_time
(
uint
index
,
uint
ranges
,
ha_rows
rows
)
{
return
rows2double
(
ranges
+
rows
);
}
virtual
bool
fast_key_read
()
{
return
0
;}
virtual
const
key_map
&
keys_to_use_for_scanning
()
{
return
key_map_empty
;
}
virtual
const
key_map
*
keys_to_use_for_scanning
()
{
return
&
key_map_empty
;
}
virtual
bool
has_transactions
(){
return
0
;}
virtual
uint
extra_rec_buf_length
()
{
return
0
;
}
virtual
ha_rows
estimate_number_of_rows
()
{
return
records
+
EXTRA_RECORDS
;
}
...
...
sql/mysql_priv.h
View file @
6e17f4f2
...
...
@@ -23,113 +23,13 @@
#include <signal.h>
#include <thr_lock.h>
#include <my_base.h>
/* Needed by field.h */
#include <
my
_bitmap.h>
#include <
sql
_bitmap.h>
#include <assert.h>
#ifdef __EMX__
#undef write
/* remove pthread.h macro definition for EMX */
#endif
template
<
uint
default_width
>
class
Bitmap
{
MY_BITMAP
map
;
uchar
buffer
[(
default_width
+
7
)
/
8
];
public:
Bitmap
(
uint
prefix_to_set
=
0
)
{
init
();
set_prefix
(
prefix_to_set
);
}
Bitmap
&
init
()
{
bitmap_init
(
&
map
,
buffer
,
default_width
,
0
);
return
*
this
;
}
uint
length
()
const
{
return
default_width
;
}
Bitmap
&
operator
=
(
const
Bitmap
&
map2
)
{
init
();
memcpy
(
buffer
,
map2
.
buffer
,
sizeof
(
buffer
));
return
*
this
;
}
Bitmap
&
set_bit
(
uint
n
)
{
bitmap_set_bit
(
&
map
,
n
);
return
*
this
;
}
Bitmap
&
clear_bit
(
uint
n
)
{
bitmap_clear_bit
(
&
map
,
n
);
return
*
this
;
}
Bitmap
&
set_prefix
(
uint
n
)
{
bitmap_set_prefix
(
&
map
,
n
);
return
*
this
;
}
Bitmap
&
set_all
()
{
bitmap_set_all
(
&
map
);
return
*
this
;}
Bitmap
&
clear_all
()
{
bitmap_clear_all
(
&
map
);
return
*
this
;
}
Bitmap
&
intersect
(
Bitmap
&
map2
)
{
bitmap_intersect
(
&
map
,
&
map2
.
map
);
return
*
this
;
}
Bitmap
&
intersect
(
ulonglong
map2buff
)
{
MY_BITMAP
map2
;
bitmap_init
(
&
map2
,
(
uchar
*
)
&
map2buff
,
sizeof
(
ulonglong
)
*
8
,
0
);
bitmap_intersect
(
&
map
,
&
map2
);
return
*
this
;
}
Bitmap
&
subtract
(
Bitmap
&
map2
)
{
bitmap_subtract
(
&
map
,
&
map2
.
map
);
return
*
this
;
}
Bitmap
&
merge
(
Bitmap
&
map2
)
{
bitmap_union
(
&
map
,
&
map2
.
map
);
return
*
this
;
}
my_bool
is_set
(
uint
n
)
const
{
return
bitmap_is_set
((
MY_BITMAP
*
)
&
map
,
n
);
}
my_bool
is_prefix
(
uint
n
)
const
{
return
bitmap_is_prefix
((
MY_BITMAP
*
)
&
map
,
n
);
}
my_bool
is_clear_all
()
const
{
return
bitmap_is_clear_all
((
MY_BITMAP
*
)
&
map
);
}
my_bool
is_set_all
()
const
{
return
bitmap_is_set_all
((
MY_BITMAP
*
)
&
map
);
}
my_bool
is_subset
(
const
Bitmap
&
map2
)
const
{
return
bitmap_is_subset
((
MY_BITMAP
*
)
&
map
,
(
MY_BITMAP
*
)
&
map2
.
map
);
}
my_bool
operator
==
(
const
Bitmap
&
map2
)
const
{
return
bitmap_cmp
((
MY_BITMAP
*
)
&
map
,
(
MY_BITMAP
*
)
&
map2
.
map
);
}
char
*
print
(
char
*
buf
)
const
{
char
*
s
=
buf
;
int
i
;
for
(
i
=
sizeof
(
buffer
)
-
1
;
i
>=
0
;
i
--
)
{
if
((
*
s
=
_dig_vec
[
buffer
[
i
]
>>
4
])
!=
'0'
)
break
;
if
((
*
s
=
_dig_vec
[
buffer
[
i
]
&
15
])
!=
'0'
)
break
;
}
for
(
s
++
,
i
--
;
i
>=
0
;
i
--
)
{
*
s
++=
_dig_vec
[
buffer
[
i
]
>>
4
];
*
s
++=
_dig_vec
[
buffer
[
i
]
&
15
];
}
*
s
=
0
;
return
buf
;
}
ulonglong
to_ulonglong
()
const
{
if
(
sizeof
(
buffer
)
>=
sizeof
(
ulonglong
))
return
*
(
ulonglong
*
)
buffer
;
ulonglong
x
=
0
;
memcpy
(
&
x
,
buffer
,
sizeof
(
buffer
));
return
x
;
}
};
template
<
>
class
Bitmap
<
64
>
{
ulonglong
map
;
public:
Bitmap
(
uint
prefix_to_set
=
0
)
{
set_prefix
(
prefix_to_set
);
}
Bitmap
<
64
>&
init
()
{
return
*
this
;
}
uint
length
()
const
{
return
64
;
}
Bitmap
<
64
>&
set_bit
(
uint
n
)
{
map
|=
((
ulonglong
)
1
)
<<
n
;
return
*
this
;
}
Bitmap
<
64
>&
clear_bit
(
uint
n
)
{
map
&=
~
(((
ulonglong
)
1
)
<<
n
);
return
*
this
;
}
Bitmap
<
64
>&
set_prefix
(
uint
n
)
{
if
(
n
>=
length
())
set_all
();
else
map
=
(((
ulonglong
)
1
)
<<
n
)
-
1
;
return
*
this
;
}
Bitmap
<
64
>&
set_all
()
{
map
=~
(
ulonglong
)
0
;
return
*
this
;}
Bitmap
<
64
>&
clear_all
()
{
map
=
(
ulonglong
)
0
;
return
*
this
;
}
Bitmap
<
64
>&
intersect
(
Bitmap
<
64
>&
map2
)
{
map
&=
map2
.
map
;
return
*
this
;
}
Bitmap
<
64
>&
intersect
(
ulonglong
map2
)
{
map
&=
map2
;
return
*
this
;
}
Bitmap
<
64
>&
subtract
(
Bitmap
<
64
>&
map2
)
{
map
&=
~
map2
.
map
;
return
*
this
;
}
Bitmap
<
64
>&
merge
(
Bitmap
<
64
>&
map2
)
{
map
|=
map2
.
map
;
return
*
this
;
}
my_bool
is_set
(
uint
n
)
const
{
return
test
(
map
&
(((
ulonglong
)
1
)
<<
n
));
}
my_bool
is_prefix
(
uint
n
)
const
{
return
map
==
(((
ulonglong
)
1
)
<<
n
)
-
1
;
}
my_bool
is_clear_all
()
const
{
return
map
==
(
ulonglong
)
0
;
}
my_bool
is_set_all
()
const
{
return
map
==
~
(
ulonglong
)
0
;
}
my_bool
is_subset
(
const
Bitmap
<
64
>&
map2
)
const
{
return
!
(
map
&
~
map2
.
map
);
}
my_bool
operator
==
(
const
Bitmap
<
64
>&
map2
)
const
{
return
map
==
map2
.
map
;
}
char
*
print
(
char
*
buf
)
const
{
longlong2str
(
map
,
buf
,
16
);
return
buf
;
}
ulonglong
to_ulonglong
()
const
{
return
map
;
}
};
/* TODO convert all these three maps to Bitmap classes */
typedef
ulonglong
table_map
;
/* Used for table bits in join */
typedef
Bitmap
<
64
>
key_map
;
/* Used for finding keys */
...
...
sql/opt_range.cc
View file @
6e17f4f2
...
...
@@ -305,7 +305,7 @@ static ha_rows check_quick_keys(PARAM *param,uint index,SEL_ARG *key_tree,
static
QUICK_SELECT
*
get_quick_select
(
PARAM
*
param
,
uint
index
,
SEL_ARG
*
key_tree
);
#ifndef DBUG_OFF
static
void
print_quick
(
QUICK_SELECT
*
quick
,
const
key_map
&
needed_reg
);
static
void
print_quick
(
QUICK_SELECT
*
quick
,
const
key_map
*
needed_reg
);
#endif
static
SEL_TREE
*
tree_and
(
PARAM
*
param
,
SEL_TREE
*
tree1
,
SEL_TREE
*
tree2
);
static
SEL_TREE
*
tree_or
(
PARAM
*
param
,
SEL_TREE
*
tree1
,
SEL_TREE
*
tree2
);
...
...
@@ -364,6 +364,7 @@ SQL_SELECT *make_select(TABLE *head, table_map const_tables,
SQL_SELECT
::
SQL_SELECT
()
:
quick
(
0
),
cond
(
0
),
free_cond
(
0
)
{
quick_keys
.
clear_all
();
needed_reg
.
clear_all
();
my_b_clear
(
&
file
);
}
...
...
@@ -588,9 +589,9 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
uint
idx
;
double
scan_time
;
DBUG_ENTER
(
"test_quick_select"
);
/*
DBUG_PRINT("enter",("keys_to_use: %lu prev_tables: %lu const_tables: %lu",
(ulong) keys_to_use
, (ulong) prev_tables,
(ulong) const_tables));
*/
DBUG_PRINT
(
"enter"
,(
"keys_to_use: %lu prev_tables: %lu const_tables: %lu"
,
keys_to_use
.
to_ulonglong
()
,
(
ulong
)
prev_tables
,
(
ulong
)
const_tables
));
delete
quick
;
quick
=
0
;
...
...
@@ -743,7 +744,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
my_pthread_setspecific_ptr
(
THR_MALLOC
,
old_root
);
thd
->
no_errors
=
0
;
}
DBUG_EXECUTE
(
"info"
,
print_quick
(
quick
,
needed_reg
););
DBUG_EXECUTE
(
"info"
,
print_quick
(
quick
,
&
needed_reg
););
/*
Assume that if the user is using 'limit' we will only need to scan
limit rows if we are using a key
...
...
@@ -2869,7 +2870,7 @@ print_key(KEY_PART *key_part,const char *key,uint used_length)
}
}
static
void
print_quick
(
QUICK_SELECT
*
quick
,
const
key_map
&
needed_reg
)
static
void
print_quick
(
QUICK_SELECT
*
quick
,
const
key_map
*
needed_reg
)
{
QUICK_RANGE
*
range
;
char
buf
[
MAX_KEY
/
8
+
1
];
...
...
@@ -2879,8 +2880,8 @@ static void print_quick(QUICK_SELECT *quick,const key_map& needed_reg)
List_iterator
<
QUICK_RANGE
>
li
(
quick
->
ranges
);
DBUG_LOCK_FILE
;
fprintf
(
DBUG_FILE
,
"Used quick_range on key: %d (other_keys: %s):
\n
"
,
quick
->
index
,
needed_reg
.
print
(
buf
));
fprintf
(
DBUG_FILE
,
"Used quick_range on key: %d (other_keys:
0x
%s):
\n
"
,
quick
->
index
,
needed_reg
->
print
(
buf
));
while
((
range
=
li
++
))
{
if
(
!
(
range
->
flag
&
NO_MIN_RANGE
))
...
...
sql/opt_range.h
View file @
6e17f4f2
...
...
@@ -128,7 +128,7 @@ class SQL_SELECT :public Sql_alloc {
SQL_SELECT
();
~
SQL_SELECT
();
bool
check_quick
(
THD
*
thd
,
bool
force_quick_range
,
ha_rows
limit
)
{
return
test_quick_select
(
thd
,
key_map
(
~
0
L
),
0
,
limit
,
force_quick_range
)
<
0
;
}
{
return
test_quick_select
(
thd
,
key_map
(
~
0
),
0
,
limit
,
force_quick_range
)
<
0
;
}
inline
bool
skipp_record
()
{
return
cond
?
cond
->
val_int
()
==
0
:
0
;
}
int
test_quick_select
(
THD
*
thd
,
key_map
keys
,
table_map
prev_tables
,
ha_rows
limit
,
bool
force_quick_range
=
0
);
...
...
sql/sql_bitmap.h
0 → 100644
View file @
6e17f4f2
#include <my_global.h>
//#include <mysql_version.h>
//#include <mysql_embed.h>
//#include <my_sys.h>
//#include <m_string.h>
//#include <hash.h>
//#include <signal.h>
//#include <thr_lock.h>
//#include <my_base.h>
#include <my_bitmap.h>
#include <assert.h>
template
<
uint
default_width
>
class
Bitmap
{
MY_BITMAP
map
;
uchar
buffer
[(
default_width
+
7
)
/
8
];
public:
Bitmap
()
{
init
();
}
Bitmap
(
uint
prefix_to_set
)
{
init
(
prefix_to_set
);
}
void
init
()
{
bitmap_init
(
&
map
,
buffer
,
default_width
,
0
);
}
void
init
(
uint
prefix_to_set
)
{
init
();
set_prefix
(
prefix_to_set
);
}
uint
length
()
const
{
return
default_width
;
}
Bitmap
&
operator
=
(
const
Bitmap
&
map2
)
{
init
();
memcpy
(
buffer
,
map2
.
buffer
,
sizeof
(
buffer
));
}
void
set_bit
(
uint
n
)
{
bitmap_set_bit
(
&
map
,
n
);
}
void
clear_bit
(
uint
n
)
{
bitmap_clear_bit
(
&
map
,
n
);
}
void
set_prefix
(
uint
n
)
{
bitmap_set_prefix
(
&
map
,
n
);
}
void
set_all
()
{
bitmap_set_all
(
&
map
);
}
void
clear_all
()
{
bitmap_clear_all
(
&
map
);
}
void
intersect
(
Bitmap
&
map2
)
{
bitmap_intersect
(
&
map
,
&
map2
.
map
);
}
void
intersect
(
ulonglong
map2buff
)
{
MY_BITMAP
map2
;
bitmap_init
(
&
map2
,
(
uchar
*
)
&
map2buff
,
sizeof
(
ulonglong
)
*
8
,
0
);
bitmap_intersect
(
&
map
,
&
map2
);
}
void
subtract
(
Bitmap
&
map2
)
{
bitmap_subtract
(
&
map
,
&
map2
.
map
);
}
void
merge
(
Bitmap
&
map2
)
{
bitmap_union
(
&
map
,
&
map2
.
map
);
}
my_bool
is_set
(
uint
n
)
const
{
return
bitmap_is_set
(
&
map
,
n
);
}
my_bool
is_prefix
(
uint
n
)
const
{
return
bitmap_is_prefix
(
&
map
,
n
);
}
my_bool
is_clear_all
()
const
{
return
bitmap_is_clear_all
(
&
map
);
}
my_bool
is_set_all
()
const
{
return
bitmap_is_set_all
(
&
map
);
}
my_bool
is_subset
(
const
Bitmap
&
map2
)
const
{
return
bitmap_is_subset
(
&
map
,
&
map2
.
map
);
}
my_bool
operator
==
(
const
Bitmap
&
map2
)
const
{
return
bitmap_cmp
(
&
map
,
&
map2
.
map
);
}
char
*
print
(
char
*
buf
)
const
{
char
*
s
=
buf
;
int
i
;
for
(
i
=
sizeof
(
buffer
)
-
1
;
i
>=
0
;
i
--
)
{
if
((
*
s
=
_dig_vec
[
buffer
[
i
]
>>
4
])
!=
'0'
)
break
;
if
((
*
s
=
_dig_vec
[
buffer
[
i
]
&
15
])
!=
'0'
)
break
;
}
for
(
s
++
,
i
--
;
i
>=
0
;
i
--
)
{
*
s
++=
_dig_vec
[
buffer
[
i
]
>>
4
];
*
s
++=
_dig_vec
[
buffer
[
i
]
&
15
];
}
*
s
=
0
;
return
buf
;
}
ulonglong
to_ulonglong
()
const
{
if
(
sizeof
(
buffer
)
>=
8
)
return
uint8korr
(
buffer
);
DBUG_ASSERT
(
sizeof
(
buffer
)
>=
4
);
uint4korr
(
buffer
);
}
};
template
<
>
class
Bitmap
<
64
>
{
ulonglong
map
;
public:
Bitmap
<
64
>
()
{
}
Bitmap
<
64
>
(
uint
prefix_to_set
)
{
set_prefix
(
prefix_to_set
);
}
void
init
()
{
}
void
init
(
uint
prefix_to_set
)
{
set_prefix
(
prefix_to_set
);
}
uint
length
()
const
{
return
64
;
}
void
set_bit
(
uint
n
)
{
map
|=
((
ulonglong
)
1
)
<<
n
;
}
void
clear_bit
(
uint
n
)
{
map
&=
~
(((
ulonglong
)
1
)
<<
n
);
}
void
set_prefix
(
uint
n
)
{
if
(
n
>=
length
())
set_all
();
else
map
=
(((
ulonglong
)
1
)
<<
n
)
-
1
;
}
void
set_all
()
{
map
=~
(
ulonglong
)
0
;
}
void
clear_all
()
{
map
=
(
ulonglong
)
0
;
}
void
intersect
(
Bitmap
<
64
>&
map2
)
{
map
&=
map2
.
map
;
}
void
intersect
(
ulonglong
map2
)
{
map
&=
map2
;
}
void
subtract
(
Bitmap
<
64
>&
map2
)
{
map
&=
~
map2
.
map
;
}
void
merge
(
Bitmap
<
64
>&
map2
)
{
map
|=
map2
.
map
;
}
my_bool
is_set
(
uint
n
)
const
{
return
test
(
map
&
(((
ulonglong
)
1
)
<<
n
));
}
my_bool
is_prefix
(
uint
n
)
const
{
return
map
==
(((
ulonglong
)
1
)
<<
n
)
-
1
;
}
my_bool
is_clear_all
()
const
{
return
map
==
(
ulonglong
)
0
;
}
my_bool
is_set_all
()
const
{
return
map
==
~
(
ulonglong
)
0
;
}
my_bool
is_subset
(
const
Bitmap
<
64
>&
map2
)
const
{
return
!
(
map
&
~
map2
.
map
);
}
my_bool
operator
==
(
const
Bitmap
<
64
>&
map2
)
const
{
return
map
==
map2
.
map
;
}
char
*
print
(
char
*
buf
)
const
{
longlong2str
(
map
,
buf
,
16
);
return
buf
;
}
ulonglong
to_ulonglong
()
const
{
return
map
;
}
};
sql/sql_select.cc
View file @
6e17f4f2
...
...
@@ -117,7 +117,7 @@ static int join_read_next_same_or_null(READ_RECORD *info);
static
COND
*
make_cond_for_table
(
COND
*
cond
,
table_map
table
,
table_map
used_table
);
static
Item
*
part_of_refkey
(
TABLE
*
form
,
Field
*
field
);
static
uint
find_shortest_key
(
TABLE
*
table
,
const
key_map
&
usable_keys
);
static
uint
find_shortest_key
(
TABLE
*
table
,
const
key_map
*
usable_keys
);
static
bool
test_if_skip_sort_order
(
JOIN_TAB
*
tab
,
ORDER
*
order
,
ha_rows
select_limit
,
bool
no_changes
);
static
int
create_sort_index
(
THD
*
thd
,
JOIN
*
join
,
ORDER
*
order
,
...
...
@@ -3257,13 +3257,13 @@ make_simple_join(JOIN *join,TABLE *tmp_table)
join
->
row_limit
=
join
->
unit
->
select_limit_cnt
;
join
->
do_send_rows
=
(
join
->
row_limit
)
?
1
:
0
;
join_tab
->
cache
.
buff
=
0
;
/* No cach
e
ing */
join_tab
->
cache
.
buff
=
0
;
/* No caching */
join_tab
->
table
=
tmp_table
;
join_tab
->
select
=
0
;
join_tab
->
select_cond
=
0
;
join_tab
->
quick
=
0
;
join_tab
->
type
=
JT_ALL
;
/* Map through all records */
join_tab
->
keys
.
init
(
).
set_all
();
/* test everything in quick */
join_tab
->
keys
.
init
(
~
0
);
/* test everything in quick */
join_tab
->
info
=
0
;
join_tab
->
on_expr
=
0
;
join_tab
->
ref
.
key
=
-
1
;
...
...
@@ -3591,7 +3591,7 @@ make_join_readinfo(JOIN *join, uint options)
}
else
if
(
!
table
->
used_keys
.
is_clear_all
()
&&
!
(
tab
->
select
&&
tab
->
select
->
quick
))
{
// 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
->
read_first_record
=
join_read_first
;
tab
->
type
=
JT_NEXT
;
// Read with index_first / index_next
...
...
@@ -6605,15 +6605,15 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx,
return
reverse
;
}
static
uint
find_shortest_key
(
TABLE
*
table
,
const
key_map
&
usable_keys
)
static
uint
find_shortest_key
(
TABLE
*
table
,
const
key_map
*
usable_keys
)
{
uint
min_length
=
(
uint
)
~
0
;
uint
best
=
MAX_KEY
;
if
(
!
usable_keys
.
is_clear_all
())
if
(
!
usable_keys
->
is_clear_all
())
{
for
(
uint
nr
=
0
;
nr
<
usable_keys
.
length
()
;
nr
++
)
for
(
uint
nr
=
0
;
nr
<
table
->
keys
;
nr
++
)
{
if
(
usable_keys
.
is_set
(
nr
))
if
(
usable_keys
->
is_set
(
nr
))
{
if
(
table
->
key_info
[
nr
].
key_length
<
min_length
)
{
...
...
@@ -6674,7 +6674,7 @@ test_if_subkey(ORDER *order, TABLE *table, uint ref, uint ref_key_parts,
KEY_PART_INFO
*
ref_key_part
=
table
->
key_info
[
ref
].
key_part
;
KEY_PART_INFO
*
ref_key_part_end
=
ref_key_part
+
ref_key_parts
;
for
(
nr
=
0
;
nr
<
usable_keys
.
length
()
;
nr
++
)
for
(
nr
=
0
;
nr
<
table
->
keys
;
nr
++
)
{
if
(
usable_keys
.
is_set
(
nr
)
&&
table
->
key_info
[
nr
].
key_length
<
min_length
&&
...
...
@@ -6840,7 +6840,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
*/
if
(
select_limit
>=
table
->
file
->
records
)
{
keys
=
table
->
file
->
keys_to_use_for_scanning
();
keys
=
*
table
->
file
->
keys_to_use_for_scanning
();
keys
.
merge
(
table
->
used_keys
);
}
else
...
...
@@ -6848,7 +6848,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
keys
.
intersect
(
usable_keys
);
for
(
nr
=
0
;
nr
<
keys
.
length
()
;
nr
++
)
for
(
nr
=
0
;
nr
<
table
->
keys
;
nr
++
)
{
uint
not_used
;
if
(
keys
.
is_set
(
nr
))
...
...
@@ -8845,7 +8845,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
if
(
tab
->
use_quick
==
2
)
{
char
buf
[
MAX_KEY
/
8
+
1
];
sprintf
(
buff_ptr
,
"; Range checked for each record (index map: %s)"
,
sprintf
(
buff_ptr
,
"; Range checked for each record (index map:
0x
%s)"
,
tab
->
keys
.
print
(
buf
));
buff_ptr
=
strend
(
buff_ptr
);
}
...
...
sql/table.cc
View file @
6e17f4f2
...
...
@@ -166,9 +166,9 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
outparam
->
keys
=
keys
=
disk_buff
[
0
];
outparam
->
key_parts
=
key_parts
=
disk_buff
[
1
];
}
outparam
->
keys_for_keyread
.
init
(
).
set_prefix
(
keys
);
outparam
->
keys_in_use
.
init
(
).
set_prefix
(
keys
);
outparam
->
read_only_keys
.
init
(
).
clear_all
(
);
outparam
->
keys_for_keyread
.
init
(
keys
);
outparam
->
keys_in_use
.
init
(
keys
);
outparam
->
read_only_keys
.
init
(
0
);
outparam
->
quick_keys
.
init
();
outparam
->
used_keys
.
init
();
outparam
->
keys_in_use_for_query
.
init
();
...
...
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