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
1476213e
Commit
1476213e
authored
Mar 31, 2005
by
jimw@mysql.com
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix crash in embedded server due to incorrect storage of results
in the query cache. (Bug #9549)
parent
026dbe3a
Changes
5
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
119 additions
and
21 deletions
+119
-21
libmysqld/emb_qcache.cc
libmysqld/emb_qcache.cc
+18
-18
libmysqld/emb_qcache.h
libmysqld/emb_qcache.h
+24
-3
mysql-test/r/query_cache.result
mysql-test/r/query_cache.result
+27
-0
mysql-test/t/query_cache.test
mysql-test/t/query_cache.test
+45
-0
sql/sql_cache.cc
sql/sql_cache.cc
+5
-0
No files found.
libmysqld/emb_qcache.cc
View file @
1476213e
...
...
@@ -22,7 +22,7 @@
void
Querycache_stream
::
store_char
(
char
c
)
{
if
(
data_end
==
cur_data
)
use_next_block
();
use_next_block
(
TRUE
);
*
(
cur_data
++
)
=
c
;
#ifndef DBUG_OFF
stored_size
++
;
...
...
@@ -42,13 +42,13 @@ void Querycache_stream::store_short(ushort s)
}
if
(
data_end
==
cur_data
)
{
use_next_block
();
use_next_block
(
TRUE
);
int2store
(
cur_data
,
s
);
cur_data
+=
2
;
return
;
}
*
cur_data
=
((
byte
*
)(
&
s
))[
0
];
use_next_block
();
use_next_block
(
TRUE
);
*
(
cur_data
++
)
=
((
byte
*
)(
&
s
))[
1
];
}
...
...
@@ -66,7 +66,7 @@ void Querycache_stream::store_int(uint i)
}
if
(
!
rest_len
)
{
use_next_block
();
use_next_block
(
TRUE
);
int4store
(
cur_data
,
i
);
cur_data
+=
4
;
return
;
...
...
@@ -74,7 +74,7 @@ void Querycache_stream::store_int(uint i)
char
buf
[
4
];
int4store
(
buf
,
i
);
memcpy
(
cur_data
,
buf
,
rest_len
);
use_next_block
();
use_next_block
(
TRUE
);
memcpy
(
cur_data
,
buf
+
rest_len
,
4
-
rest_len
);
cur_data
+=
4
-
rest_len
;
}
...
...
@@ -93,13 +93,13 @@ void Querycache_stream::store_ll(ulonglong ll)
}
if
(
!
rest_len
)
{
use_next_block
();
use_next_block
(
TRUE
);
int8store
(
cur_data
,
ll
);
cur_data
+=
8
;
return
;
}
memcpy
(
cur_data
,
&
ll
,
rest_len
);
use_next_block
();
use_next_block
(
TRUE
);
memcpy
(
cur_data
,
((
byte
*
)
&
ll
)
+
rest_len
,
8
-
rest_len
);
cur_data
+=
8
-
rest_len
;
}
...
...
@@ -112,14 +112,14 @@ void Querycache_stream::store_str_only(const char *str, uint str_len)
do
{
size_t
rest_len
=
data_end
-
cur_data
;
if
(
rest_len
>
str_len
)
if
(
rest_len
>
=
str_len
)
{
memcpy
(
cur_data
,
str
,
str_len
);
cur_data
+=
str_len
;
return
;
}
memcpy
(
cur_data
,
str
,
rest_len
);
use_next_block
();
use_next_block
(
TRUE
);
str_len
-=
rest_len
;
str
+=
rest_len
;
}
while
(
str_len
);
...
...
@@ -145,7 +145,7 @@ void Querycache_stream::store_safe_str(const char *str, uint str_len)
char
Querycache_stream
::
load_char
()
{
if
(
cur_data
==
data_end
)
use_next_block
();
use_next_block
(
FALSE
);
return
*
(
cur_data
++
);
}
...
...
@@ -160,13 +160,13 @@ ushort Querycache_stream::load_short()
}
if
(
data_end
==
cur_data
)
{
use_next_block
();
use_next_block
(
FALSE
);
result
=
uint2korr
(
cur_data
);
cur_data
+=
2
;
return
result
;
}
((
byte
*
)
&
result
)[
0
]
=
*
cur_data
;
use_next_block
();
use_next_block
(
FALSE
);
((
byte
*
)
&
result
)[
1
]
=
*
(
cur_data
++
);
return
result
;
}
...
...
@@ -183,14 +183,14 @@ uint Querycache_stream::load_int()
}
if
(
!
rest_len
)
{
use_next_block
();
use_next_block
(
FALSE
);
result
=
uint4korr
(
cur_data
);
cur_data
+=
4
;
return
result
;
}
char
buf
[
4
];
memcpy
(
buf
,
cur_data
,
rest_len
);
use_next_block
();
use_next_block
(
FALSE
);
memcpy
(
buf
+
rest_len
,
cur_data
,
4
-
rest_len
);
cur_data
+=
4
-
rest_len
;
result
=
uint4korr
(
buf
);
...
...
@@ -209,13 +209,13 @@ ulonglong Querycache_stream::load_ll()
}
if
(
!
rest_len
)
{
use_next_block
();
use_next_block
(
FALSE
);
result
=
uint8korr
(
cur_data
);
cur_data
+=
8
;
return
result
;
}
memcpy
(
&
result
,
cur_data
,
rest_len
);
use_next_block
();
use_next_block
(
FALSE
);
memcpy
(((
byte
*
)
&
result
)
+
rest_len
,
cur_data
,
8
-
rest_len
);
cur_data
+=
8
-
rest_len
;
return
result
;
...
...
@@ -226,7 +226,7 @@ void Querycache_stream::load_str_only(char *buffer, uint str_len)
do
{
size_t
rest_len
=
data_end
-
cur_data
;
if
(
rest_len
>
str_len
)
if
(
rest_len
>
=
str_len
)
{
memcpy
(
buffer
,
cur_data
,
str_len
);
cur_data
+=
str_len
;
...
...
@@ -234,7 +234,7 @@ void Querycache_stream::load_str_only(char *buffer, uint str_len)
break
;
}
memcpy
(
buffer
,
cur_data
,
rest_len
);
use_next_block
();
use_next_block
(
FALSE
);
str_len
-=
rest_len
;
buffer
+=
rest_len
;
}
while
(
str_len
);
...
...
libmysqld/emb_qcache.h
View file @
1476213e
...
...
@@ -22,22 +22,43 @@ class Querycache_stream
uint
headers_len
;
public:
#ifndef DBUG_OFF
Query_cache_block
*
first_block
;
uint
stored_size
;
#endif
Querycache_stream
(
Query_cache_block
*
ini_block
,
uint
ini_headers_len
)
:
block
(
ini_block
),
headers_len
(
ini_headers_len
)
{
use_next_block
();
cur_data
=
((
byte
*
)
block
)
+
headers_len
;
data_end
=
cur_data
+
(
block
->
used
-
headers_len
);
#ifndef DBUG_OFF
first_block
=
ini_block
;
stored_size
=
0
;
#endif
}
void
use_next_block
()
void
use_next_block
(
bool
writing
)
{
/*
This shouldn't be called if there is only one block, or to loop
around to the first block again. That means we're trying to write
more data than we allocated space for.
*/
DBUG_ASSERT
(
block
->
next
!=
block
);
DBUG_ASSERT
(
block
->
next
!=
first_block
);
block
=
block
->
next
;
/*
While writing, update the type of each block as we write to it.
While reading, make sure that the block is of the expected type.
*/
if
(
writing
)
block
->
type
=
Query_cache_block
::
RES_CONT
;
else
DBUG_ASSERT
(
block
->
type
==
Query_cache_block
::
RES_CONT
);
cur_data
=
((
byte
*
)
block
)
+
headers_len
;
data_end
=
cur_data
+
(
block
->
used
-
headers_len
);
}
void
store_char
(
char
c
);
void
store_short
(
ushort
s
);
void
store_int
(
uint
i
);
...
...
mysql-test/r/query_cache.result
View file @
1476213e
This diff is collapsed.
Click to expand it.
mysql-test/t/query_cache.test
View file @
1476213e
...
...
@@ -684,4 +684,49 @@ repair table t1;
show
status
like
'qcache_queries_in_cache'
;
drop
table
t1
;
# Bug #9549: Make sure cached queries that span more than one cache block
# are handled properly in the embedded server.
# We just want a small query cache, so we can fragment it easily
set
GLOBAL
query_cache_size
=
64
*
1024
;
# This actually gives us a usable cache size of about 48K
# Each table is about 14K
create
table
t1
(
a
text
);
insert
into
t1
values
(
repeat
(
'abcdefghijklmnopqrstuvwxyz'
,
550
));
create
table
t2
(
a
text
);
insert
into
t2
values
(
repeat
(
'ijklmnopqrstuvwxyzabcdefgh'
,
550
));
# Load a query from each table into the query cache
--
disable_result_log
select
a
from
t1
;
# Q1
select
a
from
t2
;
# Q2
--
enable_result_log
show
status
like
'Qcache_%_blocks'
;
# Now the cache looks like (14K for Q1)(14K for Q2)(20K free)
# Flush Q1 from the cache by adding an out-of-order chunk to t1
insert
into
t1
select
reverse
(
a
)
from
t1
;
show
status
like
'Qcache_%_blocks'
;
# Now the cache looks like (14K free)(14K for Q2)(20K free)
# Load our new data into the query cache
--
disable_result_log
select
a
from
t1
;
# Q3
--
enable_result_log
show
status
like
'Qcache_%_blocks'
;
# Now the cache should be like (14K for Q3)(14K for Q2)(14K for Q3)(6K free)
# Note that Q3 is split across two chunks!
# Load Q3 from the cache, and actually pay attention to the results
select
a
from
t1
;
flush
query
cache
;
drop
table
t1
,
t2
;
set
GLOBAL
query_cache_size
=
0
;
sql/sql_cache.cc
View file @
1476213e
...
...
@@ -1933,6 +1933,11 @@ my_bool Query_cache::write_result_data(Query_cache_block **result_block,
type
=
Query_cache_block
::
RES_CONT
;
}
while
(
block
!=
*
result_block
);
#else
/*
Set type of first block, emb_store_querycache_result() will handle
the others.
*/
(
*
result_block
)
->
type
=
type
;
Querycache_stream
qs
(
*
result_block
,
headers_len
);
emb_store_querycache_result
(
&
qs
,
(
THD
*
)
data
);
#endif
/*!EMBEDDED_LIBRARY*/
...
...
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