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
87fd219d
Commit
87fd219d
authored
Dec 13, 2001
by
monty@hundin.mysql.fi
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fixed sleep time in mysql-test-run
Fixed bug in query cache. Cleaned up des_crypt code.
parent
8bef3771
Changes
24
Hide whitespace changes
Inline
Side-by-side
Showing
24 changed files
with
828 additions
and
384 deletions
+828
-384
Docs/manual.texi
Docs/manual.texi
+8
-6
mysql-test/mysql-test-run.sh
mysql-test/mysql-test-run.sh
+18
-9
mysql-test/r/group_by.result
mysql-test/r/group_by.result
+47
-0
mysql-test/r/innodb_cache.result
mysql-test/r/innodb_cache.result
+15
-0
mysql-test/r/query_cache.result
mysql-test/r/query_cache.result
+2
-14
mysql-test/r/union.result
mysql-test/r/union.result
+8
-0
mysql-test/t/func_str.test
mysql-test/t/func_str.test
+1
-0
mysql-test/t/innodb_cache-master.opt
mysql-test/t/innodb_cache-master.opt
+1
-0
mysql-test/t/innodb_cache.test
mysql-test/t/innodb_cache.test
+14
-0
mysql-test/t/query_cache.test
mysql-test/t/query_cache.test
+2
-13
mysql-test/t/union.test
mysql-test/t/union.test
+2
-0
mysys/my_winsem.c
mysys/my_winsem.c
+74
-100
sql/des_key_file.cc
sql/des_key_file.cc
+58
-50
sql/item_strfunc.cc
sql/item_strfunc.cc
+108
-115
sql/item_strfunc.h
sql/item_strfunc.h
+2
-3
sql/mysql_priv.h
sql/mysql_priv.h
+2
-2
sql/mysqld.cc
sql/mysqld.cc
+0
-3
sql/sql_acl.cc
sql/sql_acl.cc
+28
-6
sql/sql_cache.cc
sql/sql_cache.cc
+361
-11
sql/sql_cache.h
sql/sql_cache.h
+4
-0
sql/sql_delete.cc
sql/sql_delete.cc
+20
-21
sql/sql_parse.cc
sql/sql_parse.cc
+9
-5
sql/sql_union.cc
sql/sql_union.cc
+28
-18
sql/sql_yacc.yy
sql/sql_yacc.yy
+16
-8
No files found.
Docs/manual.texi
View file @
87fd219d
...
@@ -11282,7 +11282,7 @@ mysql> SELECT name, birth, death,
...
@@ -11282,7 +11282,7 @@ mysql> SELECT name, birth, death,
+--------+------------+------------+------+
+--------+------------+------------+------+
@end example
@end example
The query uses @code{death IS NOT NULL} rather than @code{death
!=
NULL}
The query uses @code{death IS NOT NULL} rather than @code{death
<>
NULL}
because @code{NULL} is a special value. This is explained later.
because @code{NULL} is a special value. This is explained later.
@xref{Working with NULL, , Working with @code{NULL}}.
@xref{Working with NULL, , Working with @code{NULL}}.
...
@@ -11367,12 +11367,12 @@ The @code{NULL} value can be surprising until you get used to it.
...
@@ -11367,12 +11367,12 @@ The @code{NULL} value can be surprising until you get used to it.
Conceptually, @code{NULL} means missing value or unknown value and it
Conceptually, @code{NULL} means missing value or unknown value and it
is treated somewhat differently than other values. To test for @code{NULL},
is treated somewhat differently than other values. To test for @code{NULL},
you cannot use the arithmetic comparison operators such as @code{=}, @code{<},
you cannot use the arithmetic comparison operators such as @code{=}, @code{<},
or @code{
!=
}. To demonstrate this for yourself, try the following query:
or @code{
<>
}. To demonstrate this for yourself, try the following query:
@example
@example
mysql> SELECT 1 = NULL, 1
!=
NULL, 1 < NULL, 1 > NULL;
mysql> SELECT 1 = NULL, 1
<>
NULL, 1 < NULL, 1 > NULL;
+----------+-----------+----------+----------+
+----------+-----------+----------+----------+
| 1 = NULL | 1
!=
NULL | 1 < NULL | 1 > NULL |
| 1 = NULL | 1
<>
NULL | 1 < NULL | 1 > NULL |
+----------+-----------+----------+----------+
+----------+-----------+----------+----------+
| NULL | NULL | NULL | NULL |
| NULL | NULL | NULL | NULL |
+----------+-----------+----------+----------+
+----------+-----------+----------+----------+
...
@@ -11395,7 +11395,7 @@ The default truth value from a boolean operation is 1.
...
@@ -11395,7 +11395,7 @@ The default truth value from a boolean operation is 1.
This special treatment of @code{NULL} is why, in the previous section, it
This special treatment of @code{NULL} is why, in the previous section, it
was necessary to determine which animals are no longer alive using
was necessary to determine which animals are no longer alive using
@code{death IS NOT NULL} instead of @code{death
!=
NULL}.
@code{death IS NOT NULL} instead of @code{death
<>
NULL}.
@node Pattern matching, Counting rows, Working with NULL, Retrieving data
@node Pattern matching, Counting rows, Working with NULL, Retrieving data
...
@@ -11413,7 +11413,7 @@ SQL pattern matching allows you to use @samp{_} to match any single
...
@@ -11413,7 +11413,7 @@ SQL pattern matching allows you to use @samp{_} to match any single
character and @samp{%} to match an arbitrary number of characters (including
character and @samp{%} to match an arbitrary number of characters (including
zero characters). In MySQL, SQL patterns are case insensitive by
zero characters). In MySQL, SQL patterns are case insensitive by
default. Some examples are shown below. Note that you do not use @code{=}
default. Some examples are shown below. Note that you do not use @code{=}
or @code{
!=
} when you use SQL patterns; use the @code{LIKE} or @code{NOT
or @code{
<>
} when you use SQL patterns; use the @code{LIKE} or @code{NOT
LIKE} comparison operators instead.
LIKE} comparison operators instead.
To find names beginning with @samp{b}:
To find names beginning with @samp{b}:
...
@@ -46285,6 +46285,8 @@ Our TODO section contains what we plan to have in 4.0. @xref{TODO MySQL 4.0}.
...
@@ -46285,6 +46285,8 @@ Our TODO section contains what we plan to have in 4.0. @xref{TODO MySQL 4.0}.
@itemize @bullet
@itemize @bullet
@item
@item
Fixed problem with @code{GRANT} when using @code{lower_case_table_names == 1}.
@item
Changed @code{SELECT ... IN SHARE MODE} to
Changed @code{SELECT ... IN SHARE MODE} to
@code{SELECT .. LOCK IN SHARE MODE} (as in MySQL 3.23).
@code{SELECT .. LOCK IN SHARE MODE} (as in MySQL 3.23).
@item
@item
mysql-test/mysql-test-run.sh
View file @
87fd219d
...
@@ -46,7 +46,7 @@ which ()
...
@@ -46,7 +46,7 @@ which ()
sleep_until_file_deleted
()
sleep_until_file_deleted
()
{
{
file
=
$1
file
=
$1
loop
=
$SLEEP_TIME
loop
=
$SLEEP_TIME
_FOR_DELETE
while
(
test
$loop
-gt
0
)
while
(
test
$loop
-gt
0
)
do
do
sleep
1
sleep
1
...
@@ -61,7 +61,8 @@ sleep_until_file_deleted ()
...
@@ -61,7 +61,8 @@ sleep_until_file_deleted ()
sleep_until_file_exists
()
sleep_until_file_exists
()
{
{
file
=
$1
file
=
$1
loop
=
60
# Should be long enough enough for all cases
loop
=
$2
org_time
=
$2
while
(
test
$loop
-gt
0
)
while
(
test
$loop
-gt
0
)
do
do
sleep
1
sleep
1
...
@@ -71,7 +72,7 @@ sleep_until_file_exists ()
...
@@ -71,7 +72,7 @@ sleep_until_file_exists ()
fi
fi
loop
=
`
expr
$loop
- 1
`
loop
=
`
expr
$loop
- 1
`
done
done
echo
"ERROR:
$file
was not created in
60
seconds; Aborting"
echo
"ERROR:
$file
was not created in
$org_time
seconds; Aborting"
exit
1
;
exit
1
;
}
}
...
@@ -172,7 +173,11 @@ DO_GCOV=""
...
@@ -172,7 +173,11 @@ DO_GCOV=""
DO_GDB
=
""
DO_GDB
=
""
DO_DDD
=
""
DO_DDD
=
""
DO_CLIENT_GDB
=
""
DO_CLIENT_GDB
=
""
SLEEP_TIME
=
10
SLEEP_TIME_FOR_DELETE
=
10
SLEEP_TIME_FOR_FIRST_MASTER
=
200
# Enough time to create innodb tables
SLEEP_TIME_FOR_SECOND_MASTER
=
30
SLEEP_TIME_FOR_FIRST_SLAVE
=
30
SLEEP_TIME_FOR_SECOND_SLAVE
=
30
CHARACTER_SET
=
latin1
CHARACTER_SET
=
latin1
DBUSER
=
""
DBUSER
=
""
START_WAIT_TIMEOUT
=
3
START_WAIT_TIMEOUT
=
3
...
@@ -235,7 +240,6 @@ while test $# -gt 0; do
...
@@ -235,7 +240,6 @@ while test $# -gt 0; do
EXTRA_MYSQL_TEST_OPT
=
"
$EXTRA_MYSQL_TEST_OPT
$1
"
;;
EXTRA_MYSQL_TEST_OPT
=
"
$EXTRA_MYSQL_TEST_OPT
$1
"
;;
--sleep
=
*
)
--sleep
=
*
)
EXTRA_MYSQL_TEST_OPT
=
"
$EXTRA_MYSQL_TEST_OPT
$1
"
EXTRA_MYSQL_TEST_OPT
=
"
$EXTRA_MYSQL_TEST_OPT
$1
"
SLEEP_TIME
=
`
$ECHO
"
$1
"
|
$SED
-e
"s;--sleep=;;"
`
;;
;;
--mysqld
=
*
)
--mysqld
=
*
)
TMP
=
`
$ECHO
"
$1
"
|
$SED
-e
"s;--mysqld=;;"
`
TMP
=
`
$ECHO
"
$1
"
|
$SED
-e
"s;--mysqld=;;"
`
...
@@ -260,8 +264,9 @@ while test $# -gt 0; do
...
@@ -260,8 +264,9 @@ while test $# -gt 0; do
fi
fi
DO_GDB
=
1
DO_GDB
=
1
# We must use manager, as things doesn't work on Linux without it
# We must use manager, as things doesn't work on Linux without it
USE_MANAGER
=
1
# This needs to be checked properly
USE_RUNNING_SERVER
=
""
# USE_MANAGER=1
# USE_RUNNING_SERVER=""
;;
;;
--client-gdb
)
--client-gdb
)
if
[
x
$BINARY_DIST
=
x1
]
;
then
if
[
x
$BINARY_DIST
=
x1
]
;
then
...
@@ -755,7 +760,8 @@ EOF
...
@@ -755,7 +760,8 @@ EOF
else
else
manager_launch master
$MYSQLD
$master_args
manager_launch master
$MYSQLD
$master_args
fi
fi
sleep_until_file_exists
$MASTER_MYPID
sleep_until_file_exists
$MASTER_MYPID
$wait_for_master
wait_for_master
=
$SLEEP_TIME_FOR_SECOND_MASTER
MASTER_RUNNING
=
1
MASTER_RUNNING
=
1
}
}
...
@@ -847,7 +853,8 @@ start_slave()
...
@@ -847,7 +853,8 @@ start_slave()
manager_launch
$slave_ident
$SLAVE_MYSQLD
$slave_args
manager_launch
$slave_ident
$SLAVE_MYSQLD
$slave_args
fi
fi
eval
"SLAVE
$1_RUNNING
=1"
eval
"SLAVE
$1_RUNNING
=1"
sleep_until_file_exists
$slave_pid
sleep_until_file_exists
$slave_pid
$wait_for_slave
wait_for_slave
=
$SLEEP_TIME_FOR_SECOND_SLAVE
}
}
mysql_start
()
mysql_start
()
...
@@ -1143,6 +1150,8 @@ then
...
@@ -1143,6 +1150,8 @@ then
# Remove files that can cause problems
# Remove files that can cause problems
$RM
-f
$MYSQL_TEST_DIR
/var/run/
*
$MYSQL_TEST_DIR
/var/tmp/
*
$RM
-f
$MYSQL_TEST_DIR
/var/run/
*
$MYSQL_TEST_DIR
/var/tmp/
*
wait_for_master
=
$SLEEP_TIME_FOR_FIRST_MASTER
wait_for_slave
=
$SLEEP_TIME_FOR_FIRST_SLAVE
$ECHO
"Installing Test Databases"
$ECHO
"Installing Test Databases"
mysql_install_db
mysql_install_db
start_manager
start_manager
...
...
mysql-test/r/group_by.result
View file @
87fd219d
...
@@ -216,3 +216,50 @@ select 1+1,"a",count(*) from t1 where foo in (2);
...
@@ -216,3 +216,50 @@ select 1+1,"a",count(*) from t1 where foo in (2);
1+1 a count(*)
1+1 a count(*)
2 a 0
2 a 0
drop table t1;
drop table t1;
CREATE TABLE t1 (
spID int(10) unsigned,
userID int(10) unsigned,
score smallint(5) unsigned,
key (spid),
key (score)
);
INSERT INTO t1 VALUES (1,1,1),(2,2,2),(2,1,1),(3,3,3),(4,3,3),(5,3,3);
explain select userid,count(*) from t1 group by userid desc;
table type possible_keys key key_len ref rows Extra
t1 ALL NULL NULL NULL NULL 6 Using temporary
select userid,count(*) from t1 group by userid desc;
userid count(*)
3 3
2 1
1 2
explain select spid,count(*) from t1 where spid between 1 and 2 group by spid desc;
table type possible_keys key key_len ref rows Extra
t1 range spID spID 5 NULL 2 where used; Using index
explain select spid,count(*) from t1 where spid between 1 and 2 group by spid;
table type possible_keys key key_len ref rows Extra
t1 range spID spID 5 NULL 2 where used; Using index
select spid,count(*) from t1 where spid between 1 and 2 group by spid;
spid count(*)
1 1
2 2
select spid,count(*) from t1 where spid between 1 and 2 group by spid desc;
spid count(*)
explain select sql_big_result spid,sum(userid) from t1 group by spid desc;
table type possible_keys key key_len ref rows Extra
t1 ALL NULL NULL NULL NULL 6 Using filesort
select sql_big_result spid,sum(userid) from t1 group by spid desc;
spid sum(userid)
5 3
4 3
3 3
2 3
1 1
explain select sql_big_result score,count(*) from t1 group by score desc;
table type possible_keys key key_len ref rows Extra
t1 index NULL score 3 NULL 6 Using index
select sql_big_result score,count(*) from t1 group by score desc;
score count(*)
3 3
2 1
1 2
drop table t1;
mysql-test/r/innodb_cache.result
0 → 100644
View file @
87fd219d
drop table if exists t1;
set autocommit=0;
create table t1 (a int not null) type=innodb;
insert into t1 values (1),(2),(3);
select * from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 0
drop table t1;
commit;
set autocommit=1;
mysql-test/r/query_cache.result
View file @
87fd219d
flush query cache;
flush query cache;
reset query cache;
reset query cache;
flush status;
flush status;
drop table if exists t1,t2,t3;
drop table if exists t1,t2,t3;
...
@@ -148,20 +150,6 @@ show status like "Qcache_queries_in_cache";
...
@@ -148,20 +150,6 @@ show status like "Qcache_queries_in_cache";
Variable_name Value
Variable_name Value
Qcache_queries_in_cache 0
Qcache_queries_in_cache 0
drop table t1, t2, t3;
drop table t1, t2, t3;
set autocommit=0;
create table t1 (a int not null) type=innodb;
insert into t1 values (1),(2),(3);
select * from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 0
drop table t1;
commit;
set autocommit=1;
create table t1 (a int not null);
create table t1 (a int not null);
insert into t1 values (1),(2),(3);
insert into t1 values (1),(2),(3);
create table t2 (a int not null);
create table t2 (a int not null);
...
...
mysql-test/r/union.result
View file @
87fd219d
...
@@ -74,6 +74,14 @@ a b
...
@@ -74,6 +74,14 @@ a b
2 b
2 b
3 c
3 c
4 d
4 d
(select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1);
a b
1 a
(select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by b desc;
a b
3 c
2 b
1 a
explain select a,b from t1 union all select a,b from t2;
explain select a,b from t1 union all select a,b from t2;
table type possible_keys key key_len ref rows Extra
table type possible_keys key key_len ref rows Extra
t1 ALL NULL NULL NULL NULL 4
t1 ALL NULL NULL NULL NULL 4
...
...
mysql-test/t/func_str.test
View file @
87fd219d
...
@@ -35,6 +35,7 @@ select insert('txs',2,1,'hi'),insert('is ',4,0,'a'),insert('txxxxt',2,4,'es');
...
@@ -35,6 +35,7 @@ select insert('txs',2,1,'hi'),insert('is ',4,0,'a'),insert('txxxxt',2,4,'es');
select
replace
(
'aaaa'
,
'a'
,
'b'
),
replace
(
'aaaa'
,
'aa'
,
'b'
),
replace
(
'aaaa'
,
'a'
,
'bb'
),
replace
(
'aaaa'
,
''
,
'b'
),
replace
(
'bbbb'
,
'a'
,
'c'
);
select
replace
(
'aaaa'
,
'a'
,
'b'
),
replace
(
'aaaa'
,
'aa'
,
'b'
),
replace
(
'aaaa'
,
'a'
,
'bb'
),
replace
(
'aaaa'
,
''
,
'b'
),
replace
(
'bbbb'
,
'a'
,
'c'
);
select
replace
(
concat
(
lcase
(
concat
(
'THIS'
,
' '
,
'IS'
,
' '
,
'A'
,
' '
)),
ucase
(
'false'
),
' '
,
'test'
),
'FALSE'
,
'REAL'
)
;
select
replace
(
concat
(
lcase
(
concat
(
'THIS'
,
' '
,
'IS'
,
' '
,
'A'
,
' '
)),
ucase
(
'false'
),
' '
,
'test'
),
'FALSE'
,
'REAL'
)
;
select
soundex
(
''
),
soundex
(
'he'
),
soundex
(
'hello all folks'
);
select
soundex
(
''
),
soundex
(
'he'
),
soundex
(
'hello all folks'
);
--
replace_result
$
1
$aa
$
4
OSUA5cjdx0RUQ08opV27
/
aaqPiZY5xR5l
.
select
password
(
'test'
),
length
(
encrypt
(
'test'
)),
encrypt
(
'test'
,
'aa'
);
select
password
(
'test'
),
length
(
encrypt
(
'test'
)),
encrypt
(
'test'
,
'aa'
);
select
md5
(
'hello'
);
select
md5
(
'hello'
);
select
repeat
(
'monty'
,
5
),
concat
(
'*'
,
space
(
5
),
'*'
);
select
repeat
(
'monty'
,
5
),
concat
(
'*'
,
space
(
5
),
'*'
);
...
...
mysql-test/t/innodb_cache-master.opt
0 → 100644
View file @
87fd219d
--set-variable=query_cache_size=1M
mysql-test/t/innodb_cache.test
0 → 100644
View file @
87fd219d
--
source
include
/
have_innodb
.
inc
#
# Without auto_commit.
#
drop
table
if
exists
t1
;
set
autocommit
=
0
;
create
table
t1
(
a
int
not
null
)
type
=
innodb
;
insert
into
t1
values
(
1
),(
2
),(
3
);
select
*
from
t1
;
show
status
like
"Qcache_queries_in_cache"
;
drop
table
t1
;
commit
;
set
autocommit
=
1
;
mysql-test/t/query_cache.test
View file @
87fd219d
--
source
include
/
have_innodb
.
inc
#
#
# Tests with query cache
# Tests with query cache
#
#
# Reset query cache variables.
# Reset query cache variables.
flush
query
cache
;
# This crashed in some versions
flush
query
cache
;
# This crashed in some versions
reset
query
cache
;
reset
query
cache
;
flush
status
;
flush
status
;
drop
table
if
exists
t1
,
t2
,
t3
;
drop
table
if
exists
t1
,
t2
,
t3
;
...
@@ -73,17 +73,6 @@ delete from t3 where a=10;
...
@@ -73,17 +73,6 @@ delete from t3 where a=10;
show
status
like
"Qcache_queries_in_cache"
;
show
status
like
"Qcache_queries_in_cache"
;
drop
table
t1
,
t2
,
t3
;
drop
table
t1
,
t2
,
t3
;
#
#
# Without auto_commit.
#
set
autocommit
=
0
;
create
table
t1
(
a
int
not
null
)
type
=
innodb
;
insert
into
t1
values
(
1
),(
2
),(
3
);
select
*
from
t1
;
show
status
like
"Qcache_queries_in_cache"
;
drop
table
t1
;
commit
;
set
autocommit
=
1
;
#
# FLUSH QUERY CACHE
# FLUSH QUERY CACHE
#
#
create
table
t1
(
a
int
not
null
);
create
table
t1
(
a
int
not
null
);
...
...
mysql-test/t/union.test
View file @
87fd219d
...
@@ -18,6 +18,8 @@ select 't1',b,count(*) from t1 group by b UNION select 't2',b,count(*) from t2 g
...
@@ -18,6 +18,8 @@ select 't1',b,count(*) from t1 group by b UNION select 't2',b,count(*) from t2 g
#test alternate syntax for unions
#test alternate syntax for unions
(
select
a
,
b
from
t1
limit
2
)
union
all
(
select
a
,
b
from
t2
order
by
a
)
limit
4
;
(
select
a
,
b
from
t1
limit
2
)
union
all
(
select
a
,
b
from
t2
order
by
a
)
limit
4
;
(
select
a
,
b
from
t1
limit
2
)
union
all
(
select
a
,
b
from
t2
order
by
a
limit
1
);
(
select
a
,
b
from
t1
limit
2
)
union
all
(
select
a
,
b
from
t2
order
by
a
limit
1
)
order
by
b
desc
;
# Test some error conditions with UNION
# Test some error conditions with UNION
explain
select
a
,
b
from
t1
union
all
select
a
,
b
from
t2
;
explain
select
a
,
b
from
t1
union
all
select
a
,
b
from
t2
;
...
...
mysys/my_winsem.c
View file @
87fd219d
...
@@ -4,10 +4,10 @@
...
@@ -4,10 +4,10 @@
* Module: my_semaphore.c (Original: semaphore.c from pthreads library)
* Module: my_semaphore.c (Original: semaphore.c from pthreads library)
*
*
* Purpose:
* Purpose:
*
Semaphores aren't actually part of the PThreads standard.
*
Semaphores aren't actually part of the PThreads standard.
*
They are defined by the POSIX Standard:
*
They are defined by the POSIX Standard:
*
*
*
POSIX 1003.1b-1993
(POSIX.1b)
*
POSIX 1003.1b-1993
(POSIX.1b)
*
*
* -------------------------------------------------------------
* -------------------------------------------------------------
*
*
...
@@ -52,33 +52,27 @@
...
@@ -52,33 +52,27 @@
DOCPUBLIC
DOCPUBLIC
This function initializes an unnamed semaphore. the
This function initializes an unnamed semaphore. the
initial value of the semaphore is 'value'
initial value of the semaphore is 'value'
PARAMETERS
PARAMETERS
sem
sem Pointer to an instance of sem_t
pointer to an instance of sem_t
pshared If zero, this semaphore may only be shared between
pshared
threads in the same process.
if zero, this semaphore may only be shared between
If nonzero, the semaphore can be shared between
threads in the same process.
processes
if nonzero, the semaphore can be shared between
processes
value Initial value of the semaphore counter
value
initial value of the semaphore counter
DESCRIPTION
This function initializes an unnamed semaphore. The
initial value of the semaphore is set to 'value'.
RESULTS
RESULTS
0 successfully created semaphore,
0 Successfully created semaphore,
-1 failed, error in errno
-1 Failed, error in errno
ERRNO
ERRNO
EINVAL
'sem' is not a valid semaphore,
EINVAL
'sem' is not a valid semaphore,
ENOSPC a
required resource has been exhausted,
ENOSPC A
required resource has been exhausted,
ENOSYS s
emaphores are not supported,
ENOSYS S
emaphores are not supported,
EPERM t
he process lacks appropriate privilege
EPERM T
he process lacks appropriate privilege
*/
*/
int
int
...
@@ -111,10 +105,10 @@ sem_init (sem_t *sem, int pshared, unsigned int value)
...
@@ -111,10 +105,10 @@ sem_init (sem_t *sem, int pshared, unsigned int value)
InitializeCriticalSection
(
&
sem
->
sem_lock_cs
);
InitializeCriticalSection
(
&
sem
->
sem_lock_cs
);
}
}
#else
/* HAVE_CREATESEMAPHORE */
#else
/* HAVE_CREATESEMAPHORE */
*
sem
=
CreateSemaphore
(
NULL
,
/* Always NULL */
*
sem
=
CreateSemaphore
(
NULL
,
/* Always NULL */
value
,
/* Initial value */
value
,
/* Initial value */
0x7FFFFFFFL
,
/* Maximum value */
0x7FFFFFFFL
,
/* Maximum value */
NULL
);
/* Name */
NULL
);
/* Name */
if
(
!*
sem
)
if
(
!*
sem
)
result
=
ENOSPC
;
result
=
ENOSPC
;
#endif
/* HAVE_CREATESEMAPHORE */
#endif
/* HAVE_CREATESEMAPHORE */
...
@@ -133,20 +127,15 @@ sem_init (sem_t *sem, int pshared, unsigned int value)
...
@@ -133,20 +127,15 @@ sem_init (sem_t *sem, int pshared, unsigned int value)
This function destroys an unnamed semaphore.
This function destroys an unnamed semaphore.
PARAMETERS
PARAMETERS
sem
sem Pointer to an instance of sem_t
pointer to an instance of sem_t
DESCRIPTION
This function destroys an unnamed semaphore.
RESULTS
RESULTS
0 s
uccessfully destroyed semaphore,
0 S
uccessfully destroyed semaphore,
-1 f
ailed, error in errno
-1 F
ailed, error in errno
ERRNO
ERRNO
EINVAL 'sem' is not a valid semaphore,
EINVAL 'sem' is not a valid semaphore,
ENOSYS semaphores are not supported,
ENOSYS Semaphores are not supported,
EBUSY threads (or processes) are currently
EBUSY Threads (or processes) are currently blocked on 'sem'
blocked on 'sem'
*/
*/
int
int
...
@@ -154,7 +143,7 @@ sem_destroy (sem_t * sem)
...
@@ -154,7 +143,7 @@ sem_destroy (sem_t * sem)
{
{
int
result
=
0
;
int
result
=
0
;
#ifdef EXTRA_DEBUG
#ifdef EXTRA_DEBUG
if
(
sem
==
NULL
||
*
sem
==
NULL
)
if
(
sem
==
NULL
||
*
sem
==
NULL
)
{
{
errno
=
EINVAL
;
errno
=
EINVAL
;
...
@@ -183,27 +172,24 @@ sem_destroy (sem_t * sem)
...
@@ -183,27 +172,24 @@ sem_destroy (sem_t * sem)
/*
/*
DOCPUBLIC
DOCPUBLIC
This function tries to wait on a semaphore.
PARAMETERS
sem
pointer to an instance of sem_t
DESCRIPTION
This function tries to wait on a semaphore. If the
This function tries to wait on a semaphore. If the
semaphore value is greater than zero, it decreases
semaphore value is greater than zero, it decreases
its value by one. If the semaphore value is zero, then
its value by one. If the semaphore value is zero, then
this function returns immediately with the error EAGAIN
this function returns immediately with the error EAGAIN
PARAMETERS
sem Pointer to an instance of sem_t
RESULTS
RESULTS
0 successfully decreased semaphore,
0 Successfully decreased semaphore,
-1 failed, error in errno
-1 Failed, error in errno
ERRNO
ERRNO
EAGAIN t
he semaphore was already locked,
EAGAIN T
he semaphore was already locked,
EINVAL
'sem' is not a valid semaphore,
EINVAL
'sem' is not a valid semaphore,
ENOSYS s
emaphores are not supported,
ENOSYS S
emaphores are not supported,
EINTR t
he function was interrupted by a signal,
EINTR T
he function was interrupted by a signal,
EDEADLK a
deadlock condition was detected.
EDEADLK A
deadlock condition was detected.
*/
*/
int
int
...
@@ -214,7 +200,7 @@ sem_trywait(sem_t * sem)
...
@@ -214,7 +200,7 @@ sem_trywait(sem_t * sem)
int
errno
=
EINVAL
;
int
errno
=
EINVAL
;
return
-
1
;
return
-
1
;
#else
/* HAVE_CREATESEMAPHORE */
#else
/* HAVE_CREATESEMAPHORE */
#ifdef EXTRA_DEBUG
#ifdef EXTRA_DEBUG
if
(
sem
==
NULL
||
*
sem
==
NULL
)
if
(
sem
==
NULL
||
*
sem
==
NULL
)
{
{
errno
=
EINVAL
;
errno
=
EINVAL
;
...
@@ -234,7 +220,7 @@ sem_trywait(sem_t * sem)
...
@@ -234,7 +220,7 @@ sem_trywait(sem_t * sem)
#ifndef HAVE_CREATESEMAPHORE
#ifndef HAVE_CREATESEMAPHORE
static
void
static
void
ptw32_decrease_semaphore
(
sem_t
*
sem
)
ptw32_decrease_semaphore
(
sem_t
*
sem
)
{
{
EnterCriticalSection
(
&
sem
->
sem_lock_cs
);
EnterCriticalSection
(
&
sem
->
sem_lock_cs
);
...
@@ -267,13 +253,6 @@ ptw32_increase_semaphore(sem_t * sem, unsigned int n)
...
@@ -267,13 +253,6 @@ ptw32_increase_semaphore(sem_t * sem, unsigned int n)
/*
/*
------------------------------------------------------
------------------------------------------------------
DOCPUBLIC
DOCPUBLIC
This function waits on a semaphore.
PARAMETERS
sem
pointer to an instance of sem_t
DESCRIPTION
This function waits on a semaphore. If the
This function waits on a semaphore. If the
semaphore value is greater than zero, it decreases
semaphore value is greater than zero, it decreases
its value by one. If the semaphore value is zero, then
its value by one. If the semaphore value is zero, then
...
@@ -281,15 +260,18 @@ ptw32_increase_semaphore(sem_t * sem, unsigned int n)
...
@@ -281,15 +260,18 @@ ptw32_increase_semaphore(sem_t * sem, unsigned int n)
successfully decrease the value or until interrupted by
successfully decrease the value or until interrupted by
a signal.
a signal.
PARAMETERS
sem Pointer to an instance of sem_t
RESULTS
RESULTS
0 successfully decreased semaphore,
0 Successfully decreased semaphore,
-1 failed, error in errno
-1 Failed, error in errno
ERRNO
EINVAL 'sem' is not a valid semaphore,
ENOSYS semaphores are not supported,
EINTR the function was interrupted by a signal,
EDEADLK a deadlock condition was detected.
ERRNO
EINVAL 'Sem' is not a valid semaphore,
ENOSYS Semaphores are not supported,
EINTR The function was interrupted by a signal,
EDEADLK A deadlock condition was detected.
*/
*/
int
int
...
@@ -297,7 +279,7 @@ sem_wait(sem_t *sem)
...
@@ -297,7 +279,7 @@ sem_wait(sem_t *sem)
{
{
int
result
;
int
result
;
#ifdef EXTRA_DEBUG
#ifdef EXTRA_DEBUG
if
(
sem
==
NULL
||
*
sem
==
NULL
)
if
(
sem
==
NULL
||
*
sem
==
NULL
)
{
{
errno
=
EINVAL
;
errno
=
EINVAL
;
...
@@ -331,30 +313,27 @@ sem_wait(sem_t *sem)
...
@@ -331,30 +313,27 @@ sem_wait(sem_t *sem)
/*
/*
------------------------------------------------------
------------------------------------------------------
DOCPUBLIC
DOCPUBLIC
This function posts a wakeup to a semaphore.
PARAMETERS
sem
pointer to an instance of sem_t
DESCRIPTION
This function posts a wakeup to a semaphore. If there
This function posts a wakeup to a semaphore. If there
are waiting threads (or processes), one is awakened;
are waiting threads (or processes), one is awakened;
otherwise, the semaphore value is incremented by one.
otherwise, the semaphore value is incremented by one.
PARAMETERS
sem Pointer to an instance of sem_t
RESULTS
RESULTS
0 successfully posted semaphore,
0 Successfully posted semaphore,
-1 failed, error in errno
-1 Failed, error in errno
ERRNO
ERRNO
EINVAL
'sem' is not a valid semaphore,
EINVAL
'sem' is not a valid semaphore,
ENOSYS s
emaphores are not supported,
ENOSYS S
emaphores are not supported,
*/
*/
int
int
sem_post
(
sem_t
*
sem
)
sem_post
(
sem_t
*
sem
)
{
{
#ifdef EXTRA_DEBUG
#ifdef EXTRA_DEBUG
if
(
sem
==
NULL
||
*
sem
==
NULL
)
if
(
sem
==
NULL
||
*
sem
==
NULL
)
{
{
errno
=
EINVAL
;
errno
=
EINVAL
;
...
@@ -378,32 +357,27 @@ sem_post (sem_t * sem)
...
@@ -378,32 +357,27 @@ sem_post (sem_t * sem)
/*
/*
------------------------------------------------------
------------------------------------------------------
DOCPUBLIC
DOCPUBLIC
This function posts multiple wakeups to a semaphore.
PARAMETERS
sem
pointer to an instance of sem_t
count
counter, must be greater than zero.
DESCRIPTION
This function posts multiple wakeups to a semaphore. If there
This function posts multiple wakeups to a semaphore. If there
are waiting threads (or processes), n <= count are awakened;
are waiting threads (or processes), n <= count are awakened;
the semaphore value is incremented by count - n.
the semaphore value is incremented by count - n.
PARAMETERS
sem Pointer to an instance of sem_t
count Counter, must be greater than zero.
RESULTS
RESULTS
0 successfully posted semaphore,
0 Successfully posted semaphore,
-1 failed, error in errno
-1 Failed, error in errno
ERRNO
ERRNO
EINVAL 'sem' is not a valid semaphore
EINVAL 'sem' is not a valid semaphore or count is less
or count is less
than or equal to zero.
than or equal to zero.
*/
*/
int
int
sem_post_multiple
(
sem_t
*
sem
,
int
count
)
sem_post_multiple
(
sem_t
*
sem
,
int
count
)
{
{
#ifdef EXTRA_DEBUG
#ifdef EXTRA_DEBUG
if
(
sem
==
NULL
||
*
sem
==
NULL
||
count
<=
0
)
if
(
sem
==
NULL
||
*
sem
==
NULL
||
count
<=
0
)
{
{
errno
=
EINVAL
;
errno
=
EINVAL
;
...
...
sql/des_key_file.cc
View file @
87fd219d
...
@@ -15,72 +15,80 @@
...
@@ -15,72 +15,80 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <mysql_priv.h>
#include <mysql_priv.h>
#include <m_ctype.h>
#ifdef HAVE_OPENSSL
#ifdef HAVE_OPENSSL
/*
/*
Function which loads DES keys from plaintext file
Function which loads DES keys from plaintext file into memory on MySQL
into memory on MySQL server startup and on command
server startup and on command FLUSH DES_KEYS. Blame tonu@spam.ee on bugs ;)
FLUSH DES_KEYS. Blame tonu@spam.ee on bugs ;)
*/
*/
void
struct
st_des_keyschedule
des_keyschedule
[
10
];
uint
default_des_key
;
void
load_des_key_file
(
const
char
*
file_name
)
load_des_key_file
(
const
char
*
file_name
)
{
{
FILE
*
file
;
File
file
;
int
ret
=
0
;
char
offset
;
char
buf
[
1024
];
des_cblock
ivec
=
{
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
};
des_cblock
ivec
=
{
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
};
st_des_keyblock
keyblock
;
char
offset
;
IO_CACHE
io
;
DBUG_ENTER
(
"load_des_key_file"
);
DBUG_ENTER
(
"load_des_key_file"
);
VOID
(
pthread_mutex_lock
(
&
LOCK_open
));
DBUG_PRINT
(
"enter"
,(
"name: %s"
,
file_name
));
DBUG_PRINT
(
"enter"
,(
"name: %s"
,
file_name
));
if
(
!
(
file
=
my_fopen
(
file_name
,
O_RDONLY
,
MYF
(
MY_WME
))))
{
VOID
(
pthread_mutex_lock
(
&
LOCK_open
));
goto
error_noclose
;
if
((
file
=
my_open
(
file_name
,
O_RDONLY
|
O_BINARY
,
MYF
(
MY_WME
)))
<
0
||
}
init_io_cache
(
&
io
,
file
,
IO_SIZE
*
2
,
READ_CACHE
,
0
,
0
,
MYF
(
MY_WME
)))
while
(
!
feof
(
file
))
goto
error
;
bzero
((
char
*
)
des_keyschedule
,
sizeof
(
struct
st_des_keyschedule
)
*
10
);
default_des_key
=
15
;
// Impossible key
for
(;;)
{
{
if
((
my_fread
(
file
,
&
offset
,
1
,
MY_WME
))
!=
1
)
char
*
start
,
*
end
;
goto
error_close
;
char
buf
[
1024
]
;
fgets
(
buf
,
sizeof
(
buf
),
file
)
;
st_des_keyblock
keyblock
;
int
len
=
strlen
(
buf
)
;
uint
length
;
if
(
len
-->=
1
)
buf
[
len
]
=
'\0'
;
if
(
!
(
length
=
my_b_gets
(
&
io
,
buf
,
sizeof
(
buf
)
-
1
)))
/* We make good 24-byte (168 bit) key from given plaintext key with MD5 */
break
;
// End of file
offset
-=
'0'
;
offset
=
buf
[
0
]
;
if
(
offset
>=
0
&&
offset
<=
9
)
if
(
offset
>=
'0'
&&
offset
<=
'9'
)
// If ok key
{
{
EVP_BytesToKey
(
EVP_des_ede3_cbc
(),
EVP_md5
(),
NULL
,
offset
=
(
char
)
(
offset
-
'0'
);
(
uchar
*
)
buf
,
// Remove newline and possible other control characters
strlen
(
buf
),
1
,(
uchar
*
)
&
keyblock
,
ivec
);
for
(
start
=
buf
+
1
;
isspace
(
*
start
)
;
start
++
)
;
des_set_key_unchecked
(
&
keyblock
.
key1
,
des_keyschedule
[(
int
)
offset
].
ks1
);
end
=
buf
+
length
;
des_set_key_unchecked
(
&
keyblock
.
key2
,
des_keyschedule
[(
int
)
offset
].
ks2
);
for
(
end
=
strend
(
buf
)
;
end
>
start
&&
iscntrl
(
end
[
-
1
])
;
end
--
)
;
des_set_key_unchecked
(
&
keyblock
.
key3
,
des_keyschedule
[(
int
)
offset
].
ks3
);
}
if
(
start
!=
end
)
{
// We make good 24-byte (168 bit) key from given plaintext key with MD5
EVP_BytesToKey
(
EVP_des_ede3_cbc
(),
EVP_md5
(),
NULL
,
(
uchar
*
)
start
,
(
int
)
(
end
-
start
),
1
,
(
uchar
*
)
&
keyblock
,
ivec
);
des_set_key_unchecked
(
&
keyblock
.
key1
,
des_keyschedule
[(
int
)
offset
].
ks1
);
des_set_key_unchecked
(
&
keyblock
.
key2
,
des_keyschedule
[(
int
)
offset
].
ks2
);
des_set_key_unchecked
(
&
keyblock
.
key3
,
des_keyschedule
[(
int
)
offset
].
ks3
);
if
(
default_des_key
==
15
)
default_des_key
=
(
uint
)
offset
;
// use first as def.
}
}
else
else
{
{
DBUG_PRINT
(
"des"
,(
"wrong offset: %
d
"
,
offset
));
DBUG_PRINT
(
"des"
,(
"wrong offset: %
c
"
,
offset
));
}
}
}
}
error_close:
(
void
)
my_fclose
(
file
,
MYF
(
MY_WME
));
error:
error_noclose:
if
(
file
>=
0
)
{
my_close
(
file
,
MYF
(
0
));
end_io_cache
(
&
io
);
}
VOID
(
pthread_mutex_unlock
(
&
LOCK_open
));
VOID
(
pthread_mutex_unlock
(
&
LOCK_open
));
/* if (ret)
do something; */
DBUG_VOID_RETURN
;
DBUG_VOID_RETURN
;
}
}
/*
This function is used to load right key with DES_ENCRYPT(text,integer)
*/
st_des_keyschedule
*
des_key
(
int
key
)
{
DBUG_ENTER
(
"des_key"
);
DBUG_PRINT
(
"exit"
,(
"return: %x"
,
&
des_keyschedule
[
key
]));
DBUG_RETURN
(
&
des_keyschedule
[
key
]);
}
#endif
/* HAVE_OPENSSL */
#endif
/* HAVE_OPENSSL */
sql/item_strfunc.cc
View file @
87fd219d
...
@@ -75,7 +75,11 @@ String *Item_func_md5::val_str(String *str)
...
@@ -75,7 +75,11 @@ String *Item_func_md5::val_str(String *str)
my_MD5Init
(
&
context
);
my_MD5Init
(
&
context
);
my_MD5Update
(
&
context
,(
unsigned
char
*
)
sptr
->
ptr
(),
sptr
->
length
());
my_MD5Update
(
&
context
,(
unsigned
char
*
)
sptr
->
ptr
(),
sptr
->
length
());
my_MD5Final
(
digest
,
&
context
);
my_MD5Final
(
digest
,
&
context
);
str
->
alloc
(
32
);
// Ensure that memory is free
if
(
str
->
alloc
(
32
))
// Ensure that memory is free
{
null_value
=
1
;
return
0
;
}
sprintf
((
char
*
)
str
->
ptr
(),
sprintf
((
char
*
)
str
->
ptr
(),
"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
,
"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
,
digest
[
0
],
digest
[
1
],
digest
[
2
],
digest
[
3
],
digest
[
0
],
digest
[
1
],
digest
[
2
],
digest
[
3
],
...
@@ -201,162 +205,150 @@ void Item_func_concat::fix_length_and_dec()
...
@@ -201,162 +205,150 @@ void Item_func_concat::fix_length_and_dec()
}
}
}
}
#define bin_to_ascii(c) ((c)>=38?((c)-38+'a'):(c)>=12?((c)-12+'A'):(c)+'.')
#define ascii_to_bin(c) ((c)<=57 ? (c)-46 : (c)<=90 ? (c)-53 : (c)-59)
/*
/*
Function des_encrypt() by tonu@spam.ee
Function des_encrypt() by tonu@spam.ee & monty
Works only if compiled with OpenSSL library support.
Works only if compiled with OpenSSL library support.
Output always starts with magic char "1" and all
This returns a binary string where first character is
encrypted output is encoded into ASCII-protected
CHAR(128 | tail-length << 4 | key-number).
container.
If one uses a string key key_number is 0.
Original input is returned as output if input string
begins with magic "1". Credit card number always begin
with 4,5 or 6.
Encryption result is longer than original by formula:
Encryption result is longer than original by formula:
new_length=
(8-(original_length % 8))*2
+1
new_length=
(8-(original_length % 8))
+1
*/
*/
String
*
Item_func_des_encrypt
::
val_str
(
String
*
str
)
String
*
Item_func_des_encrypt
::
val_str
(
String
*
str
)
{
{
String
*
res
=
args
[
0
]
->
val_str
(
str
);
#ifdef HAVE_OPENSSL
#ifdef HAVE_OPENSSL
des_cblock
ivec
=
{
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
};
des_cblock
ivec
=
{
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
};
struct
st_des_keyblock
keyblock
;
struct
st_des_keyblock
keyblock
;
struct
st_des_keyschedule
keyschedule
;
struct
st_des_keyschedule
keyschedule
;
struct
st_des_keyschedule
*
keyschedule_ptr
=&
keyschedule
;
struct
st_des_keyschedule
*
keyschedule_ptr
=&
keyschedule
;
uint
key_number
=
15
;
String
*
res
=
args
[
0
]
->
val_str
(
str
);
if
((
null_value
=
args
[
0
]
->
null_value
))
if
((
null_value
=
args
[
0
]
->
null_value
))
return
0
;
return
0
;
if
(
res
->
length
()
==
0
)
if
(
res
->
length
()
==
0
)
return
&
empty_string
;
return
&
empty_string
;
if
(
res
->
c_ptr
()[
0
]
!=
'1'
)
// Skip encryption if already encrypted
{
if
(
args
[
1
]
->
val_int
())
{
keyschedule_ptr
=
des_key
(
args
[
1
]
->
val_int
());
}
else
{
String
*
keystr
=
args
[
1
]
->
val_str
(
&
tmp_value
);
/* We make good 24-byte (168 bit) key from given plaintext key with MD5 */
EVP_BytesToKey
(
EVP_des_ede3_cbc
(),
EVP_md5
(),
NULL
,
(
uchar
*
)
keystr
->
c_ptr
(),
(
int
)
keystr
->
length
(),
1
,(
uchar
*
)
&
keyblock
,
ivec
);
des_set_key_unchecked
(
&
keyblock
.
key1
,
keyschedule_ptr
->
ks1
);
des_set_key_unchecked
(
&
keyblock
.
key2
,
keyschedule_ptr
->
ks2
);
des_set_key_unchecked
(
&
keyblock
.
key3
,
keyschedule_ptr
->
ks3
);
}
/*
The problem: DES algorithm requires original data to be in 8-bytes
chunks. Missing bytes get filled with zeros and result of encryption
can be up to 7 bytes longer than original string. When decrypted,
we do not know the size of original string :(
We add one byte with value 0x0..0x7 to original plaintext marking
change of string length
*/
uchar
tail
=
7
-
(
res
->
length
()
%
8
);
// 0..7 marking real offsets 1..8
for
(
int
i
=
0
;
i
<
tail
;
++
i
)
res
->
append
(
'*'
);
res
->
append
(
tail
);
// Write tail length 0..7 to last pos
str
->
length
(
res
->
length
());
for
(
uint
j
=
0
;
j
<
res
->
length
()
;
++
j
)
{
DBUG_PRINT
(
"info"
,(
"## res->c_ptr()[%d]='%c'"
,
j
,
res
->
c_ptr
()[
j
]));
}
des_ede3_cbc_encrypt
(
// Real encryption
(
const
uchar
*
)(
res
->
c_ptr
()),
(
uchar
*
)(
str
->
c_ptr
()),
res
->
length
(),
keyschedule_ptr
->
ks1
,
keyschedule_ptr
->
ks2
,
keyschedule_ptr
->
ks3
,
&
ivec
,
TRUE
);
for
(
uint
j
=
0
;
j
<
res
->
length
()
;
++
j
)
{
DBUG_PRINT
(
"info"
,(
"## str->c_ptr()[%d]='%c'"
,
j
,
str
->
c_ptr
()[
j
]));
}
res
->
set
((
const
char
*
)
"1"
,(
uint
)
1
);
if
(
arg_count
==
1
)
for
(
uint
i
=
0
;
i
<
str
->
length
()
;
++
i
)
keyschedule_ptr
=
des_keyschedule
[
key_number
=
default_des_key
];
{
else
if
(
args
[
1
]
->
result_type
==
INT_RESULT
)
res
->
append
(
bin_to_ascii
((
uchar
)
str
->
c_ptr
()[
i
]
&
0x3f
));
{
res
->
append
(
bin_to_ascii
(((
uchar
)
str
->
c_ptr
()[
i
]
>>
5
)
&
0x3f
));
key_number
=
(
uint
)
args
[
1
]
->
val_int
();
}
if
(
key_number
>
9
)
goto
error
;
keyschedule_ptr
=
des_keyschedule
[
key_number
];
}
}
return
res
;
else
#else
{
const
char
*
append_str
=
"********"
;
uint
tail
,
res_length
;
String
*
keystr
=
args
[
1
]
->
val_str
(
&
tmp_value
);
if
(
!
keystr
)
goto
error
;
/* We make good 24-byte (168 bit) key from given plaintext key with MD5 */
EVP_BytesToKey
(
EVP_des_ede3_cbc
(),
EVP_md5
(),
NULL
,
(
uchar
*
)
keystr
->
ptr
(),
(
int
)
keystr
->
length
(),
1
,
(
uchar
*
)
&
keyblock
,
ivec
);
des_set_key_unchecked
(
&
keyblock
.
key1
,
keyschedule_ptr
->
ks1
);
des_set_key_unchecked
(
&
keyblock
.
key2
,
keyschedule_ptr
->
ks2
);
des_set_key_unchecked
(
&
keyblock
.
key3
,
keyschedule_ptr
->
ks3
);
}
/*
The problem: DES algorithm requires original data to be in 8-bytes
chunks. Missing bytes get filled with zeros and result of encryption
can be up to 7 bytes longer than original string. When decrypted,
we do not know the size of original string :(
We add one byte with value 0x1..0x8 as the second byte to original
plaintext marking change of string length.
*/
tail
=
(
7
-
(
res
->
length
()
+
7
)
%
8
);
// 0..7 marking extra length
res_length
=
res
->
length
()
+
tail
+
1
;
if
(
tail
&&
res
->
append
(
append_str
,
tail
)
||
tmp_value
.
alloc
(
res_length
))
goto
err
;
tmp_value
.
length
(
res_length
);
tmp_value
.[
0
]
=
(
char
)
(
128
|
tail
<<
4
|
key_number
);
// Real encryption
des_ede3_cbc_encrypt
((
const
uchar
*
)
(
res
->
ptr
()),
(
uchar
*
)
(
tmp_value
->
ptr
()
+
1
),
res
->
length
(),
keyschedule_ptr
->
ks1
,
keyschedule_ptr
->
ks2
,
keyschedule_ptr
->
ks3
,
&
ivec
,
TRUE
);
return
&
tmp_value
;
error:
#endif
/* HAVE_OPENSSL */
null_value
=
1
;
null_value
=
1
;
return
0
;
return
0
;
#endif
/* HAVE_OPENSSL */
}
}
String
*
Item_func_des_decrypt
::
val_str
(
String
*
str
)
String
*
Item_func_des_decrypt
::
val_str
(
String
*
str
)
{
{
String
*
res
=
args
[
0
]
->
val_str
(
str
);
#ifdef HAVE_OPENSSL
#ifdef HAVE_OPENSSL
des_key_schedule
ks1
,
ks2
,
ks3
;
des_key_schedule
ks1
,
ks2
,
ks3
;
des_cblock
ivec
=
{
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
};
des_cblock
ivec
=
{
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
};
struct
st_des_keyblock
keyblock
;
struct
st_des_keyblock
keyblock
;
struct
st_des_keyschedule
keyschedule
;
struct
st_des_keyschedule
keyschedule
;
struct
st_des_keyschedule
*
keyschedule_ptr
=&
keyschedule
;
struct
st_des_keyschedule
*
keyschedule_ptr
=&
keyschedule
;
String
*
res
=
args
[
0
]
->
val_str
(
str
);
if
((
null_value
=
args
[
0
]
->
null_value
))
if
((
null_value
=
args
[
0
]
->
null_value
))
return
0
;
return
0
;
if
(
res
->
length
(
)
==
0
)
if
(
res
->
length
(
0
)
<
9
||
(
res
->
length
())
%
8
!=
1
||
!
(
res
->
[
0
]
&
128
)
)
return
&
empty_string
;
return
res
;
// Skip decryption if not encrypted
if
(
res
->
c_ptr
()[
0
]
==
'1'
)
// Skip decryption if not encrypted
if
(
arg_count
==
1
)
// If automatic uncompression
{
{
str
->
set
((
const
char
*
)
0
,(
uint
)
0
);
uint
key_number
=
res
->
[
0
]
&
15
;
for
(
uint
i
=
1
;
i
<
res
->
length
()
;
i
+=
2
)
// Check if automatic key and that we have privilege to uncompress using it
{
if
(
!
(
current_thd
->
master_access
&
PROCESS_ACL
)
||
key_number
>
9
)
str
->
append
((
ascii_to_bin
(
res
->
c_ptr
()[
i
]))
goto
error
;
|
(
ascii_to_bin
(
res
->
c_ptr
()[
i
+
1
])
<<
5
));
keyschedule_ptr
=
des_keyschedule
[
key_number
-
1
];
}
if
(
args
[
1
]
->
val_int
())
{
keyschedule_ptr
=
des_key
(
args
[
1
]
->
val_int
());
}
else
{
/*
We make good 24-byte (168 bit) key
from given plaintext key with MD5
*/
String
*
keystr
=
args
[
1
]
->
val_str
(
&
tmp_value
);
EVP_BytesToKey
(
EVP_des_ede3_cbc
(),
EVP_md5
(),
NULL
,
(
uchar
*
)
keystr
->
c_ptr
(),
(
int
)
keystr
->
length
(),
1
,(
uchar
*
)
&
keyblock
,
ivec
);
/*
Here we set all 64-bit keys (56 effective) one by one
*/
des_set_key_unchecked
(
&
keyblock
.
key1
,
keyschedule_ptr
->
ks1
);
des_set_key_unchecked
(
&
keyblock
.
key2
,
keyschedule_ptr
->
ks2
);
des_set_key_unchecked
(
&
keyblock
.
key3
,
keyschedule_ptr
->
ks3
);
}
res
->
length
(
str
->
length
());
des_ede3_cbc_encrypt
(
// Real decryption
(
const
uchar
*
)(
str
->
c_ptr
()),
(
uchar
*
)(
res
->
c_ptr
()),
str
->
length
(),
keyschedule_ptr
->
ks1
,
keyschedule_ptr
->
ks2
,
keyschedule_ptr
->
ks3
,
&
ivec
,
FALSE
);
uchar
tail
=
(
res
->
c_ptr
()[
res
->
length
()
-
1
])
&
0x7
;
if
((
res
->
length
()
>
((
uint
)
1
+
tail
)))
// We should avoid negative length
res
->
length
(
res
->
length
()
-
1
-
tail
);
// (can happen with wrong key)
}
}
return
res
;
else
#else
{
// We make good 24-byte (168 bit) key from given plaintext key with MD5
String
*
keystr
=
args
[
1
]
->
val_str
(
&
tmp_value
);
if
(
!
key_str
)
goto
error
;
EVP_BytesToKey
(
EVP_des_ede3_cbc
(),
EVP_md5
(),
NULL
,
(
uchar
*
)
keystr
->
ptr
(),(
int
)
keystr
->
length
(),
1
,(
uchar
*
)
&
keyblock
,
ivec
);
// Here we set all 64-bit keys (56 effective) one by one
des_set_key_unchecked
(
&
keyblock
.
key1
,
keyschedule_ptr
->
ks1
);
des_set_key_unchecked
(
&
keyblock
.
key2
,
keyschedule_ptr
->
ks2
);
des_set_key_unchecked
(
&
keyblock
.
key3
,
keyschedule_ptr
->
ks3
);
}
if
(
tmp_value
.
alloc
(
res
->
length
()
-
1
))
goto
err
;
/* Restore old length of key */
tmp_value
.
length
(
res
->
length
()
-
1
-
(((
uchar
)
res
->
[
0
]
>>
4
)
&
7
));
des_ede3_cbc_encrypt
((
const
uchar
*
)
res
->
ptr
()
+
1
,
(
uchar
*
)
(
tmp_value
->
ptr
()),
res
->
length
()
-
1
,
keyschedule_ptr
->
ks1
,
keyschedule_ptr
->
ks2
,
keyschedule_ptr
->
ks3
,
&
ivec
,
FALSE
);
return
&
tmp_value
;
error:
#endif
/* HAVE_OPENSSL */
null_value
=
1
;
null_value
=
1
;
return
0
;
return
0
;
#endif
/* HAVE_OPENSSL */
}
}
/*
/*
**
concat with separator. First arg is the separator
concat with separator. First arg is the separator
**
concat_ws takes at least two arguments.
concat_ws takes at least two arguments.
*/
*/
String
*
Item_func_concat_ws
::
val_str
(
String
*
str
)
String
*
Item_func_concat_ws
::
val_str
(
String
*
str
)
...
@@ -1146,6 +1138,7 @@ String *Item_func_password::val_str(String *str)
...
@@ -1146,6 +1138,7 @@ String *Item_func_password::val_str(String *str)
return
str
;
return
str
;
}
}
#define bin_to_ascii(c) ((c)>=38?((c)-38+'a'):(c)>=12?((c)-12+'A'):(c)+'.')
String
*
Item_func_encrypt
::
val_str
(
String
*
str
)
String
*
Item_func_encrypt
::
val_str
(
String
*
str
)
{
{
...
...
sql/item_strfunc.h
View file @
87fd219d
...
@@ -228,9 +228,9 @@ class Item_func_des_encrypt :public Item_str_func
...
@@ -228,9 +228,9 @@ class Item_func_des_encrypt :public Item_str_func
public:
public:
Item_func_des_encrypt
(
Item
*
a
)
:
Item_str_func
(
a
)
{}
Item_func_des_encrypt
(
Item
*
a
)
:
Item_str_func
(
a
)
{}
Item_func_des_encrypt
(
Item
*
a
,
Item
*
b
)
:
Item_str_func
(
a
,
b
)
{}
Item_func_des_encrypt
(
Item
*
a
,
Item
*
b
)
:
Item_str_func
(
a
,
b
)
{}
Item_func_des_encrypt
(
Item
*
a
,
Item
*
b
,
Item
*
c
)
:
Item_str_func
(
a
,
b
,
c
)
{}
String
*
val_str
(
String
*
);
String
*
val_str
(
String
*
);
void
fix_length_and_dec
()
{
maybe_null
=
1
;
max_length
=
args
[
0
]
->
max_length
;
}
void
fix_length_and_dec
()
{
maybe_null
=
1
;
max_length
=
args
[
0
]
->
max_length
+
8
;
}
const
char
*
func_name
()
const
{
return
"des_encrypt"
;
}
const
char
*
func_name
()
const
{
return
"des_encrypt"
;
}
};
};
...
@@ -240,7 +240,6 @@ class Item_func_des_decrypt :public Item_str_func
...
@@ -240,7 +240,6 @@ class Item_func_des_decrypt :public Item_str_func
public:
public:
Item_func_des_decrypt
(
Item
*
a
)
:
Item_str_func
(
a
)
{}
Item_func_des_decrypt
(
Item
*
a
)
:
Item_str_func
(
a
)
{}
Item_func_des_decrypt
(
Item
*
a
,
Item
*
b
)
:
Item_str_func
(
a
,
b
)
{}
Item_func_des_decrypt
(
Item
*
a
,
Item
*
b
)
:
Item_str_func
(
a
,
b
)
{}
Item_func_des_decrypt
(
Item
*
a
,
Item
*
b
,
Item
*
c
)
:
Item_str_func
(
a
,
b
,
c
)
{}
String
*
val_str
(
String
*
);
String
*
val_str
(
String
*
);
void
fix_length_and_dec
()
{
maybe_null
=
1
;
max_length
=
args
[
0
]
->
max_length
;
}
void
fix_length_and_dec
()
{
maybe_null
=
1
;
max_length
=
args
[
0
]
->
max_length
;
}
const
char
*
func_name
()
const
{
return
"des_decrypt"
;
}
const
char
*
func_name
()
const
{
return
"des_decrypt"
;
}
...
...
sql/mysql_priv.h
View file @
87fd219d
...
@@ -405,9 +405,9 @@ struct st_des_keyschedule
...
@@ -405,9 +405,9 @@ struct st_des_keyschedule
{
{
des_key_schedule
ks1
,
ks2
,
ks3
;
des_key_schedule
ks1
,
ks2
,
ks3
;
};
};
extern
struct
st_des_keyschedule
des_keyschedule
[
10
];
extern
struct
st_des_keyschedule
des_keyschedule
[
9
];
extern
uint
des_default_key
;
void
load_des_key_file
(
const
char
*
file_name
);
void
load_des_key_file
(
const
char
*
file_name
);
struct
st_des_keyschedule
*
des_key
(
int
);
#endif
/* HAVE_OPENSSL */
#endif
/* HAVE_OPENSSL */
/* sql_list.c */
/* sql_list.c */
...
...
sql/mysqld.cc
View file @
87fd219d
...
@@ -243,7 +243,6 @@ static char glob_hostname[FN_REFLEN];
...
@@ -243,7 +243,6 @@ static char glob_hostname[FN_REFLEN];
#include "sslopt-vars.h"
#include "sslopt-vars.h"
#ifdef HAVE_OPENSSL
#ifdef HAVE_OPENSSL
static
char
*
des_key_file
=
0
;
static
char
*
des_key_file
=
0
;
struct
st_des_keyschedule
des_keyschedule
[
10
];
struct
st_VioSSLAcceptorFd
*
ssl_acceptor_fd
=
0
;
struct
st_VioSSLAcceptorFd
*
ssl_acceptor_fd
=
0
;
#endif
/* HAVE_OPENSSL */
#endif
/* HAVE_OPENSSL */
...
@@ -1751,8 +1750,6 @@ int main(int argc, char **argv)
...
@@ -1751,8 +1750,6 @@ int main(int argc, char **argv)
opt_use_ssl
=
0
;
opt_use_ssl
=
0
;
/* having ssl_acceptor_fd != 0 signals the use of SSL */
/* having ssl_acceptor_fd != 0 signals the use of SSL */
}
}
bzero
(
des_keyschedule
,
sizeof
(
struct
st_des_keyschedule
)
*
10
);
DBUG_PRINT
(
"des"
,(
"initializing %d bytes of %x"
,
sizeof
(
struct
st_des_keyschedule
)
*
10
,
des_keyschedule
));
if
(
des_key_file
)
if
(
des_key_file
)
load_des_key_file
(
des_key_file
);
load_des_key_file
(
des_key_file
);
#endif
/* HAVE_OPENSSL */
#endif
/* HAVE_OPENSSL */
...
...
sql/sql_acl.cc
View file @
87fd219d
...
@@ -698,12 +698,17 @@ uint acl_get(const char *host, const char *ip, const char *bin_ip,
...
@@ -698,12 +698,17 @@ uint acl_get(const char *host, const char *ip, const char *bin_ip,
{
{
uint
host_access
,
db_access
,
i
,
key_length
;
uint
host_access
,
db_access
,
i
,
key_length
;
db_access
=
0
;
host_access
=
~
0
;
db_access
=
0
;
host_access
=
~
0
;
char
key
[
ACL_KEY_LENGTH
],
*
end
;
char
key
[
ACL_KEY_LENGTH
],
*
tmp_db
,
*
end
;
acl_entry
*
entry
;
acl_entry
*
entry
;
VOID
(
pthread_mutex_lock
(
&
acl_cache
->
lock
));
VOID
(
pthread_mutex_lock
(
&
acl_cache
->
lock
));
memcpy_fixed
(
&
key
,
bin_ip
,
sizeof
(
struct
in_addr
));
memcpy_fixed
(
&
key
,
bin_ip
,
sizeof
(
struct
in_addr
));
end
=
strmov
(
strmov
(
key
+
sizeof
(
struct
in_addr
),
user
)
+
1
,
db
);
end
=
strmov
((
tmp_db
=
strmov
(
key
+
sizeof
(
struct
in_addr
),
user
)
+
1
),
db
);
if
(
lower_case_table_names
)
{
casedn_str
(
tmp_db
);
db
=
tmp_db
;
}
key_length
=
(
uint
)
(
end
-
key
);
key_length
=
(
uint
)
(
end
-
key
);
if
((
entry
=
(
acl_entry
*
)
acl_cache
->
search
(
key
,
key_length
)))
if
((
entry
=
(
acl_entry
*
)
acl_cache
->
search
(
key
,
key_length
)))
{
{
...
@@ -1377,6 +1382,11 @@ public:
...
@@ -1377,6 +1382,11 @@ public:
db
=
strdup_root
(
&
memex
,
d
);
db
=
strdup_root
(
&
memex
,
d
);
user
=
strdup_root
(
&
memex
,
u
);
user
=
strdup_root
(
&
memex
,
u
);
tname
=
strdup_root
(
&
memex
,
t
);
tname
=
strdup_root
(
&
memex
,
t
);
if
(
lower_case_table_names
)
{
casedn_str
(
db
);
casedn_str
(
tname
);
}
key_length
=
(
uint
)
strlen
(
d
)
+
(
uint
)
strlen
(
u
)
+
(
uint
)
strlen
(
t
)
+
3
;
key_length
=
(
uint
)
strlen
(
d
)
+
(
uint
)
strlen
(
u
)
+
(
uint
)
strlen
(
t
)
+
3
;
hash_key
=
(
char
*
)
alloc_root
(
&
memex
,
key_length
);
hash_key
=
(
char
*
)
alloc_root
(
&
memex
,
key_length
);
strmov
(
strmov
(
strmov
(
hash_key
,
user
)
+
1
,
db
)
+
1
,
tname
);
strmov
(
strmov
(
strmov
(
hash_key
,
user
)
+
1
,
db
)
+
1
,
tname
);
...
@@ -1398,7 +1408,13 @@ public:
...
@@ -1398,7 +1408,13 @@ public:
privs
=
cols
=
0
;
/* purecov: inspected */
privs
=
cols
=
0
;
/* purecov: inspected */
return
;
/* purecov: inspected */
return
;
/* purecov: inspected */
}
}
key_length
=
(
uint
)
strlen
(
db
)
+
(
uint
)
strlen
(
user
)
+
(
uint
)
strlen
(
tname
)
+
3
;
if
(
lower_case_table_names
)
{
casedn_str
(
db
);
casedn_str
(
tname
);
}
key_length
=
((
uint
)
strlen
(
db
)
+
(
uint
)
strlen
(
user
)
+
(
uint
)
strlen
(
tname
)
+
3
);
hash_key
=
(
char
*
)
alloc_root
(
&
memex
,
key_length
);
hash_key
=
(
char
*
)
alloc_root
(
&
memex
,
key_length
);
strmov
(
strmov
(
strmov
(
hash_key
,
user
)
+
1
,
db
)
+
1
,
tname
);
strmov
(
strmov
(
strmov
(
hash_key
,
user
)
+
1
,
db
)
+
1
,
tname
);
privs
=
(
uint
)
form
->
field
[
6
]
->
val_int
();
privs
=
(
uint
)
form
->
field
[
6
]
->
val_int
();
...
@@ -1990,7 +2006,7 @@ int mysql_grant (THD *thd, const char *db, List <LEX_USER> &list, uint rights,
...
@@ -1990,7 +2006,7 @@ int mysql_grant (THD *thd, const char *db, List <LEX_USER> &list, uint rights,
{
{
List_iterator
<
LEX_USER
>
str_list
(
list
);
List_iterator
<
LEX_USER
>
str_list
(
list
);
LEX_USER
*
Str
;
LEX_USER
*
Str
;
char
what
;
char
what
,
tmp_db
[
NAME_LEN
+
1
]
;
bool
create_new_users
=
0
;
bool
create_new_users
=
0
;
TABLE_LIST
tables
[
2
];
TABLE_LIST
tables
[
2
];
DBUG_ENTER
(
"mysql_grant"
);
DBUG_ENTER
(
"mysql_grant"
);
...
@@ -2002,6 +2018,12 @@ int mysql_grant (THD *thd, const char *db, List <LEX_USER> &list, uint rights,
...
@@ -2002,6 +2018,12 @@ int mysql_grant (THD *thd, const char *db, List <LEX_USER> &list, uint rights,
}
}
what
=
(
revoke_grant
)
?
'N'
:
'Y'
;
what
=
(
revoke_grant
)
?
'N'
:
'Y'
;
if
(
lower_case_table_names
&&
db
)
{
strmov
(
tmp_db
,
db
);
casedn_str
(
tmp_db
);
db
=
tmp_db
;
}
/* open the mysql.user and mysql.db tables */
/* open the mysql.user and mysql.db tables */
...
@@ -2220,8 +2242,8 @@ bool check_grant(THD *thd, uint want_access, TABLE_LIST *tables,
...
@@ -2220,8 +2242,8 @@ bool check_grant(THD *thd, uint want_access, TABLE_LIST *tables,
table
->
grant
.
want_privilege
=
0
;
table
->
grant
.
want_privilege
=
0
;
continue
;
// Already checked
continue
;
// Already checked
}
}
const
char
*
db
=
table
->
db
?
table
->
db
:
thd
->
db
;
GRANT_TABLE
*
grant_table
=
table_hash_search
(
thd
->
host
,
thd
->
ip
,
GRANT_TABLE
*
grant_table
=
table_hash_search
(
thd
->
host
,
thd
->
ip
,
db
,
user
,
table
->
db
,
user
,
table
->
real_name
,
0
);
table
->
real_name
,
0
);
if
(
!
grant_table
)
if
(
!
grant_table
)
{
{
...
...
sql/sql_cache.cc
View file @
87fd219d
...
@@ -201,7 +201,7 @@ stored in Query_cache_memory_bin_step structure.
...
@@ -201,7 +201,7 @@ stored in Query_cache_memory_bin_step structure.
Free memory blocks are sorted in bins in lists with size-ascending order
Free memory blocks are sorted in bins in lists with size-ascending order
(more small blocks needed frequently then bigger one).
(more small blocks needed frequently then bigger one).
6
. Packing cache.
7
. Packing cache.
Query cache packing is divided into two operation:
Query cache packing is divided into two operation:
- pack_cache
- pack_cache
...
@@ -305,7 +305,8 @@ If join_results allocated new block(s) then we need call pack_cache again.
...
@@ -305,7 +305,8 @@ If join_results allocated new block(s) then we need call pack_cache again.
#define BLOCK_UNLOCK_RD(B) { \
#define BLOCK_UNLOCK_RD(B) { \
DBUG_PRINT("lock", ("%d UNLOCK_RD 0x%lx",\
DBUG_PRINT("lock", ("%d UNLOCK_RD 0x%lx",\
__LINE__,(ulong)(B)));B->query()->unlock_reading();}
__LINE__,(ulong)(B)));B->query()->unlock_reading();}
#define DUMP(C) DBUG_EXECUTE("qcache", {(C)->queries_dump();(C)->tables_dump();})
#define DUMP(C) DBUG_EXECUTE("qcache", {\
(C)->cache_dump(); (C)->queries_dump();(C)->tables_dump();})
#else
#else
#define MUTEX_LOCK(M) pthread_mutex_lock(M)
#define MUTEX_LOCK(M) pthread_mutex_lock(M)
#define MUTEX_UNLOCK(M) pthread_mutex_unlock(M)
#define MUTEX_UNLOCK(M) pthread_mutex_unlock(M)
...
@@ -581,6 +582,7 @@ void query_cache_insert(NET *net, const char *packet, ulong length)
...
@@ -581,6 +582,7 @@ void query_cache_insert(NET *net, const char *packet, ulong length)
else
else
STRUCT_UNLOCK
(
&
query_cache
.
structure_guard_mutex
);
STRUCT_UNLOCK
(
&
query_cache
.
structure_guard_mutex
);
}
}
DBUG_EXECUTE
(
"check_querycache"
,
query_cache
.
check_integrity
(););
DBUG_VOID_RETURN
;
DBUG_VOID_RETURN
;
}
}
...
@@ -609,6 +611,7 @@ void query_cache_abort(NET *net)
...
@@ -609,6 +611,7 @@ void query_cache_abort(NET *net)
}
}
STRUCT_UNLOCK
(
&
query_cache
.
structure_guard_mutex
);
STRUCT_UNLOCK
(
&
query_cache
.
structure_guard_mutex
);
}
}
DBUG_EXECUTE
(
"check_querycache"
,
query_cache
.
check_integrity
(););
DBUG_VOID_RETURN
;
DBUG_VOID_RETURN
;
}
}
...
@@ -656,12 +659,14 @@ void query_cache_end_of_result(NET *net)
...
@@ -656,12 +659,14 @@ void query_cache_end_of_result(NET *net)
}
}
net
->
query_cache_query
=
0
;
net
->
query_cache_query
=
0
;
}
}
DBUG_EXECUTE
(
"check_querycache"
,
query_cache
.
check_integrity
(););
DBUG_VOID_RETURN
;
DBUG_VOID_RETURN
;
}
}
void
query_cache_invalidate_by_MyISAM_filename
(
const
char
*
filename
)
void
query_cache_invalidate_by_MyISAM_filename
(
const
char
*
filename
)
{
{
query_cache
.
invalidate_by_MyISAM_filename
(
filename
);
query_cache
.
invalidate_by_MyISAM_filename
(
filename
);
DBUG_EXECUTE
(
"check_querycache"
,
query_cache
.
check_integrity
(););
}
}
...
@@ -1321,6 +1326,7 @@ void Query_cache::free_cache(my_bool destruction)
...
@@ -1321,6 +1326,7 @@ void Query_cache::free_cache(my_bool destruction)
if
(
bins
[
0
].
free_blocks
==
0
)
if
(
bins
[
0
].
free_blocks
==
0
)
{
{
wreck
(
__LINE__
,
"no free memory found in (bins[0].free_blocks"
);
wreck
(
__LINE__
,
"no free memory found in (bins[0].free_blocks"
);
DBUG_VOID_RETURN
;
}
}
#endif
#endif
...
@@ -1335,12 +1341,13 @@ void Query_cache::free_cache(my_bool destruction)
...
@@ -1335,12 +1341,13 @@ void Query_cache::free_cache(my_bool destruction)
hash_free
(
&
tables
);
hash_free
(
&
tables
);
if
(
!
destruction
)
if
(
!
destruction
)
STRUCT_UNLOCK
(
&
structure_guard_mutex
);
STRUCT_UNLOCK
(
&
structure_guard_mutex
);
DBUG_EXECUTE
(
"check_querycache"
,
check_integrity
(););
}
}
DBUG_VOID_RETURN
;
DBUG_VOID_RETURN
;
}
}
/*****************************************************************************
/*****************************************************************************
Free block data
Free block data
*****************************************************************************/
*****************************************************************************/
/*
/*
...
@@ -1501,7 +1508,6 @@ Query_cache::append_result_data(Query_cache_block **current_block,
...
@@ -1501,7 +1508,6 @@ Query_cache::append_result_data(Query_cache_block **current_block,
DBUG_PRINT
(
"qcache"
,
(
"size limit reached %lu > %lu"
,
DBUG_PRINT
(
"qcache"
,
(
"size limit reached %lu > %lu"
,
query_block
->
query
()
->
length
(),
query_block
->
query
()
->
length
(),
query_cache_limit
));
query_cache_limit
));
*
current_block
=
0
;
// Mark error
DBUG_RETURN
(
0
);
DBUG_RETURN
(
0
);
}
}
if
(
*
current_block
==
0
)
if
(
*
current_block
==
0
)
...
@@ -1550,8 +1556,8 @@ Query_cache::append_result_data(Query_cache_block **current_block,
...
@@ -1550,8 +1556,8 @@ Query_cache::append_result_data(Query_cache_block **current_block,
query_block
,
query_block
,
Query_cache_block
::
RES_CONT
);
Query_cache_block
::
RES_CONT
);
/*
/*
new_block may be
not
0 even !success (if write_result_data
new_block may be
!=
0 even !success (if write_result_data
allocate
small block but failed allocate continue
allocate
a small block but failed to allocate continue)
*/
*/
if
(
new_block
!=
0
)
if
(
new_block
!=
0
)
double_linked_list_join
(
last_block
,
new_block
);
double_linked_list_join
(
last_block
,
new_block
);
...
@@ -1999,7 +2005,7 @@ Query_cache::get_free_block(ulong len, my_bool not_less, ulong min)
...
@@ -1999,7 +2005,7 @@ Query_cache::get_free_block(ulong len, my_bool not_less, ulong min)
void
Query_cache
::
free_memory_block
(
Query_cache_block
*
block
)
void
Query_cache
::
free_memory_block
(
Query_cache_block
*
block
)
{
{
DBUG_ENTER
(
"Query_cache::free_
n_unlock_
memory_block"
);
DBUG_ENTER
(
"Query_cache::free_memory_block"
);
block
->
used
=
0
;
block
->
used
=
0
;
DBUG_PRINT
(
"qcache"
,(
"first_block 0x%lx, block 0x%lx, pnext 0x%lx pprev 0x%lx"
,
DBUG_PRINT
(
"qcache"
,(
"first_block 0x%lx, block 0x%lx, pnext 0x%lx pprev 0x%lx"
,
(
ulong
)
first_block
,
(
ulong
)
block
,
block
->
pnext
,
(
ulong
)
first_block
,
(
ulong
)
block
,
block
->
pnext
,
...
@@ -2069,7 +2075,7 @@ my_bool Query_cache::append_next_free_block(Query_cache_block *block,
...
@@ -2069,7 +2075,7 @@ my_bool Query_cache::append_next_free_block(Query_cache_block *block,
DBUG_PRINT
(
"enter"
,
(
"block 0x%lx, add_size %lu"
,
(
ulong
)
block
,
DBUG_PRINT
(
"enter"
,
(
"block 0x%lx, add_size %lu"
,
(
ulong
)
block
,
add_size
));
add_size
));
if
(
next_block
->
is_free
())
if
(
next_block
!=
first_block
&&
next_block
->
is_free
())
{
{
ulong
old_len
=
block
->
length
;
ulong
old_len
=
block
->
length
;
exclude_from_free_memory_list
(
next_block
);
exclude_from_free_memory_list
(
next_block
);
...
@@ -2404,7 +2410,7 @@ my_bool Query_cache::move_by_type(byte **border,
...
@@ -2404,7 +2410,7 @@ my_bool Query_cache::move_by_type(byte **border,
char
*
data
=
(
char
*
)
block
->
data
();
char
*
data
=
(
char
*
)
block
->
data
();
byte
*
key
;
byte
*
key
;
uint
key_length
;
uint
key_length
;
key
=
query_cache_table_get_key
((
byte
*
)
block
,
&
key_length
,
0
);
key
=
query_cache_table_get_key
((
byte
*
)
block
,
&
key_length
,
0
);
hash_search
(
&
tables
,
(
byte
*
)
key
,
key_length
);
hash_search
(
&
tables
,
(
byte
*
)
key
,
key_length
);
block
->
destroy
();
block
->
destroy
();
...
@@ -2452,7 +2458,7 @@ my_bool Query_cache::move_by_type(byte **border,
...
@@ -2452,7 +2458,7 @@ my_bool Query_cache::move_by_type(byte **border,
block
->
data
())
->
result
();
block
->
data
())
->
result
();
byte
*
key
;
byte
*
key
;
uint
key_length
;
uint
key_length
;
key
=
query_cache_query_get_key
((
byte
*
)
block
,
&
key_length
,
0
);
key
=
query_cache_query_get_key
((
byte
*
)
block
,
&
key_length
,
0
);
hash_search
(
&
queries
,
(
byte
*
)
key
,
key_length
);
hash_search
(
&
queries
,
(
byte
*
)
key
,
key_length
);
memcpy
((
char
*
)
new_block
->
table
(
0
),
(
char
*
)
block
->
table
(
0
),
memcpy
((
char
*
)
new_block
->
table
(
0
),
(
char
*
)
block
->
table
(
0
),
...
@@ -2682,8 +2688,9 @@ void Query_cache::wreck(uint line, const char *message)
...
@@ -2682,8 +2688,9 @@ void Query_cache::wreck(uint line, const char *message)
DBUG_PRINT
(
"warning"
,
(
"=================================="
));
DBUG_PRINT
(
"warning"
,
(
"=================================="
));
if
(
thd
)
if
(
thd
)
thd
->
killed
=
1
;
thd
->
killed
=
1
;
bins_dump
();
cache_dump
();
cache_dump
();
/* check_integrity(); */
/* Can't call it here because of locks */
bins_dump
();
DBUG_VOID_RETURN
;
DBUG_VOID_RETURN
;
}
}
...
@@ -2821,4 +2828,347 @@ void Query_cache::tables_dump()
...
@@ -2821,4 +2828,347 @@ void Query_cache::tables_dump()
}
}
DBUG_PRINT
(
"qcache"
,
(
"--------------------"
));
DBUG_PRINT
(
"qcache"
,
(
"--------------------"
));
}
}
my_bool
Query_cache
::
check_integrity
()
{
my_bool
result
=
0
;
uint
i
;
STRUCT_LOCK
(
&
structure_guard_mutex
);
if
(
hash_check
(
&
queries
))
{
DBUG_PRINT
(
"error"
,
(
"queries hash is damaged"
));
result
=
1
;
}
if
(
hash_check
(
&
tables
))
{
DBUG_PRINT
(
"error"
,
(
"tables hash is damaged"
));
result
=
1
;
}
DBUG_PRINT
(
"qcache"
,
(
"physical address check ..."
));
ulong
free
=
0
,
used
=
0
;
Query_cache_block
*
block
=
first_block
;
do
{
DBUG_PRINT
(
"qcache"
,
(
"block 0x%lx, type %u..."
,
(
ulong
)
block
,
(
uint
)
block
->
type
));
// Check memory allocation
if
(
block
->
pnext
==
first_block
)
// Is it last block?
{
if
(
((
byte
*
)
block
)
+
block
->
length
!=
((
byte
*
)
first_block
)
+
query_cache_size
)
{
DBUG_PRINT
(
"error"
,
(
"block 0x%lx, type %u, ended at 0x%lx, but cache ended at 0x%lx"
,
(
ulong
)
block
,
(
uint
)
block
->
type
,
(
ulong
)
(((
byte
*
)
block
)
+
block
->
length
),
(
ulong
)
(((
byte
*
)
first_block
)
+
query_cache_size
)));
result
=
1
;
}
}
else
if
(((
byte
*
)
block
)
+
block
->
length
!=
((
byte
*
)
block
->
pnext
))
{
DBUG_PRINT
(
"error"
,
(
"block 0x%lx, type %u, ended at 0x%lx, but next block begining at 0x%lx"
,
(
ulong
)
block
,
(
uint
)
block
->
type
,
(
ulong
)
(((
byte
*
)
block
)
+
block
->
length
),
(
ulong
)
((
byte
*
)
block
->
pnext
)));
}
if
(
block
->
type
==
Query_cache_block
::
FREE
)
free
+=
block
->
length
;
else
used
+=
block
->
length
;
switch
(
block
->
type
)
{
case
Query_cache_block
:
:
FREE
:
{
Query_cache_memory_bin
*
bin
=
*
((
Query_cache_memory_bin
**
)
block
->
data
());
//is it correct pointer?
if
(
((
byte
*
)
bin
)
<
((
byte
*
)
bins
)
||
((
byte
*
)
bin
)
>=
((
byte
*
)
first_block
))
{
DBUG_PRINT
(
"error"
,
(
"free block 0x%lx have bin pointer 0x%lx beyaond of bins array bounds [0x%lx,0x%lx]"
,
(
ulong
)
block
,
(
ulong
)
bin
,
(
ulong
)
bins
,
(
ulong
)
first_block
));
result
=
1
;
}
else
{
int
idx
=
(((
byte
*
)
bin
)
-
((
byte
*
)
bins
))
/
sizeof
(
Query_cache_memory_bin
);
if
(
in_list
(
bins
[
idx
].
free_blocks
,
block
,
"free memory"
))
result
=
1
;
}
break
;
}
case
Query_cache_block
:
:
TABLE
:
if
(
in_list
(
tables_blocks
[
block
->
table
()
->
type
()],
block
,
"tables"
))
result
=
1
;
break
;
case
Query_cache_block
:
:
QUERY
:
if
(
in_list
(
queries_blocks
,
block
,
"query"
))
result
=
1
;
break
;
case
Query_cache_block
:
:
RES_INCOMPLETE
:
case
Query_cache_block
:
:
RES_BEG
:
case
Query_cache_block
:
:
RES_CONT
:
case
Query_cache_block
:
:
RESULT
:
{
Query_cache_block
*
query_block
=
block
->
result
()
->
parent
();
if
(
((
byte
*
)
query_block
)
<
((
byte
*
)
first_block
)
||
((
byte
*
)
query_block
)
>=
(((
byte
*
)
first_block
)
+
query_cache_size
))
{
DBUG_PRINT
(
"error"
,
(
"result block 0x%lx have query block pointer 0x%lx beyaond of block pool bounds [0x%lx,0x%lx]"
,
(
ulong
)
block
,
(
ulong
)
query_block
,
(
ulong
)
first_block
,
(
ulong
)
(((
byte
*
)
first_block
)
+
query_cache_size
)));
result
=
1
;
}
else
{
if
(
in_list
(
queries_blocks
,
query_block
,
"query from results"
))
result
=
1
;
if
(
in_list
(
query_block
->
query
()
->
result
(),
block
,
"results"
))
result
=
1
;
}
break
;
}
default:
DBUG_PRINT
(
"error"
,
(
"block 0x%lx have incorrect type %u"
,
block
,
block
->
type
));
result
=
1
;
}
block
=
block
->
pnext
;
}
while
(
block
!=
first_block
);
if
(
used
+
free
!=
query_cache_size
)
{
DBUG_PRINT
(
"error"
,
(
"used memory (%lu) + free memory (%lu) != query_cache_size (%lu)"
,
used
,
free
,
query_cache_size
));
result
=
1
;
}
if
(
free
!=
free_memory
)
{
DBUG_PRINT
(
"error"
,
(
"free memory (%lu) != free_memory (%lu)"
,
free
,
free_memory
));
result
=
1
;
}
DBUG_PRINT
(
"qcache"
,
(
"check queries ..."
));
if
((
block
=
queries_blocks
))
{
do
{
DBUG_PRINT
(
"qcache"
,
(
"block 0x%lx, type %u..."
,
(
ulong
)
block
,
(
uint
)
block
->
type
));
uint
length
;
byte
*
key
=
query_cache_query_get_key
((
byte
*
)
block
,
&
length
,
0
);
gptr
val
=
hash_search
(
&
queries
,
key
,
length
);
if
(((
gptr
)
block
)
!=
val
)
{
DBUG_PRINT
(
"error"
,
(
"block 0x%lx found in queries hash like 0x%lx"
,
(
ulong
)
block
,
(
ulong
)
val
));
}
if
(
in_blocks
(
block
))
result
=
1
;
Query_cache_block
*
results
=
block
->
query
()
->
result
();
if
(
results
)
{
Query_cache_block
*
result_block
=
results
;
do
{
DBUG_PRINT
(
"qcache"
,
(
"block 0x%lx, type %u..."
,
(
ulong
)
block
,
(
uint
)
block
->
type
));
if
(
in_blocks
(
result_block
))
result
=
1
;
result_block
=
result_block
->
next
;
}
while
(
result_block
!=
results
);
}
block
=
block
->
next
;
}
while
(
block
!=
queries_blocks
);
}
DBUG_PRINT
(
"qcache"
,
(
"check tables ..."
));
for
(
i
=
0
;
(
int
)
i
<
(
int
)
Query_cache_table
::
TYPES_NUMBER
;
i
++
)
{
if
((
block
=
tables_blocks
[
i
]))
{
do
{
DBUG_PRINT
(
"qcache"
,
(
"block 0x%lx, type %u..."
,
(
ulong
)
block
,
(
uint
)
block
->
type
));
uint
length
;
byte
*
key
=
query_cache_table_get_key
((
byte
*
)
block
,
&
length
,
0
);
gptr
val
=
hash_search
(
&
tables
,
key
,
length
);
if
(((
gptr
)
block
)
!=
val
)
{
DBUG_PRINT
(
"error"
,
(
"block 0x%lx found in tables hash like 0x%lx"
,
(
ulong
)
block
,
(
ulong
)
val
));
}
if
(
in_blocks
(
block
))
result
=
1
;
block
=
block
->
next
;
}
while
(
block
!=
tables_blocks
[
i
]);
}
}
DBUG_PRINT
(
"qcache"
,
(
"check free blocks"
));
for
(
i
=
0
;
i
<
mem_bin_num
;
i
++
)
{
if
((
block
=
bins
[
i
].
free_blocks
))
{
uint
count
=
0
;
do
{
DBUG_PRINT
(
"qcache"
,
(
"block 0x%lx, type %u..."
,
(
ulong
)
block
,
(
uint
)
block
->
type
));
if
(
in_blocks
(
block
))
result
=
1
;
count
++
;
block
=
block
->
next
;
}
while
(
block
!=
bins
[
i
].
free_blocks
);
if
(
count
!=
bins
[
i
].
number
)
{
DBUG_PRINT
(
"qcache"
,
(
"bin[%d].number is %d, but bin have %d blocks"
,
bins
[
i
].
number
,
count
));
result
=
1
;
}
}
}
DBUG_ASSERT
(
result
==
0
);
STRUCT_UNLOCK
(
&
structure_guard_mutex
);
return
result
;
}
my_bool
Query_cache
::
in_blocks
(
Query_cache_block
*
point
)
{
my_bool
result
=
0
;
Query_cache_block
*
block
=
point
;
//back
do
{
if
(
block
->
pprev
->
pnext
!=
block
)
{
DBUG_PRINT
(
"error"
,
(
"block 0x%lx in physical list is incorrect linked, prev block 0x%lx refered as next to 0x%lx (check from 0x%lx)"
,
(
ulong
)
block
,
(
ulong
)
block
->
pprev
,
(
ulong
)
block
->
pprev
->
pnext
,
(
ulong
)
point
));
//back trace
for
(;
block
!=
point
;
block
=
block
->
pnext
)
DBUG_PRINT
(
"error"
,
(
"back trace 0x%lx"
,
(
ulong
)
block
));
result
=
1
;
goto
err1
;
}
block
=
block
->
pprev
;
}
while
(
block
!=
first_block
&&
block
!=
point
);
if
(
block
!=
first_block
)
{
DBUG_PRINT
(
"error"
,
(
"block 0x%lx (0x%lx<-->0x%lx) not owned by pysical list"
,
(
ulong
)
block
,
(
ulong
)
block
->
pprev
,
(
ulong
)
block
->
pnext
));
return
1
;
}
err1:
//forward
block
=
point
;
do
{
if
(
block
->
pnext
->
pprev
!=
block
)
{
DBUG_PRINT
(
"error"
,
(
"block 0x%lx in physicel list is incorrect linked, next block 0x%lx refered as prev to 0x%lx (check from 0x%lx)"
,
(
ulong
)
block
,
(
ulong
)
block
->
pnext
,
(
ulong
)
block
->
pnext
->
pprev
,
(
ulong
)
point
));
//back trace
for
(;
block
!=
point
;
block
=
block
->
pprev
)
DBUG_PRINT
(
"error"
,
(
"back trace 0x%lx"
,
(
ulong
)
block
));
result
=
1
;
goto
err2
;
}
block
=
block
->
pnext
;
}
while
(
block
!=
first_block
);
err2:
return
result
;
}
my_bool
Query_cache
::
in_list
(
Query_cache_block
*
root
,
Query_cache_block
*
point
,
const
char
*
name
)
{
my_bool
result
=
0
;
Query_cache_block
*
block
=
point
;
//back
do
{
if
(
block
->
prev
->
next
!=
block
)
{
DBUG_PRINT
(
"error"
,
(
"block 0x%lx in list '%s' 0x%lx is incorrect linked, prev block 0x%lx refered as next to 0x%lx (check from 0x%lx)"
,
(
ulong
)
block
,
name
,
(
ulong
)
root
,
(
ulong
)
block
->
prev
,
(
ulong
)
block
->
prev
->
next
,
(
ulong
)
point
));
//back trace
for
(;
block
!=
point
;
block
=
block
->
next
)
DBUG_PRINT
(
"error"
,
(
"back trace 0x%lx"
,
(
ulong
)
block
));
result
=
1
;
goto
err1
;
}
block
=
block
->
prev
;
}
while
(
block
!=
root
&&
block
!=
point
);
if
(
block
!=
root
)
{
DBUG_PRINT
(
"error"
,
(
"block 0x%lx (0x%lx<-->0x%lx) not owned by list '%s' 0x%lx"
,
(
ulong
)
block
,
(
ulong
)
block
->
prev
,
(
ulong
)
block
->
next
,
name
,
(
ulong
)
root
));
return
1
;
}
err1:
// forward
block
=
point
;
do
{
if
(
block
->
next
->
prev
!=
block
)
{
DBUG_PRINT
(
"error"
,
(
"block 0x%lx in list '%s' 0x%lx is incorrect linked, next block 0x%lx refered as prev to 0x%lx (check from 0x%lx)"
,
(
ulong
)
block
,
name
,
(
ulong
)
root
,
(
ulong
)
block
->
next
,
(
ulong
)
block
->
next
->
prev
,
(
ulong
)
point
));
//back trace
for
(;
block
!=
point
;
block
=
block
->
prev
)
DBUG_PRINT
(
"error"
,
(
"back trace 0x%lx"
,
(
ulong
)
block
));
result
=
1
;
goto
err2
;
}
block
=
block
->
next
;
}
while
(
block
!=
root
);
err2:
return
result
;
}
#endif
/* DBUG_OFF */
#endif
/* DBUG_OFF */
sql/sql_cache.h
View file @
87fd219d
...
@@ -379,6 +379,10 @@ protected:
...
@@ -379,6 +379,10 @@ protected:
void
cache_dump
();
void
cache_dump
();
void
queries_dump
();
void
queries_dump
();
void
tables_dump
();
void
tables_dump
();
my_bool
check_integrity
();
my_bool
in_list
(
Query_cache_block
*
root
,
Query_cache_block
*
point
,
const
char
*
name
);
my_bool
in_blocks
(
Query_cache_block
*
point
);
#endif
#endif
friend
void
query_cache_insert
(
NET
*
net
,
const
char
*
packet
,
ulong
length
);
friend
void
query_cache_insert
(
NET
*
net
,
const
char
*
packet
,
ulong
length
);
friend
void
query_cache_end_of_result
(
NET
*
net
);
friend
void
query_cache_end_of_result
(
NET
*
net
);
...
...
sql/sql_delete.cc
View file @
87fd219d
...
@@ -384,6 +384,13 @@ void multi_delete::send_error(uint errcode,const char *err)
...
@@ -384,6 +384,13 @@ void multi_delete::send_error(uint errcode,const char *err)
}
}
/*
Do delete from other tables.
Returns values:
0 ok
1 error
*/
int
multi_delete
::
do_deletes
(
bool
from_send_error
)
int
multi_delete
::
do_deletes
(
bool
from_send_error
)
{
{
int
error
=
0
,
counter
=
0
;
int
error
=
0
,
counter
=
0
;
...
@@ -420,7 +427,8 @@ int multi_delete::do_deletes (bool from_send_error)
...
@@ -420,7 +427,8 @@ int multi_delete::do_deletes (bool from_send_error)
{
{
TABLE_LIST
table_list
;
TABLE_LIST
table_list
;
bzero
((
char
*
)
&
table_list
,
sizeof
(
table_list
));
bzero
((
char
*
)
&
table_list
,
sizeof
(
table_list
));
table_list
.
name
=
table
->
table_name
;
table_list
.
real_name
=
table_being_deleted
->
real_name
;
table_list
.
name
=
table
->
table_name
;
table_list
.
real_name
=
table_being_deleted
->
real_name
;
table_list
.
table
=
table
;
table_list
.
table
=
table
;
table_list
.
grant
=
table
->
grant
;
table_list
.
grant
=
table
->
grant
;
table_list
.
db
=
table_being_deleted
->
db
;
table_list
.
db
=
table_being_deleted
->
db
;
...
@@ -432,23 +440,20 @@ int multi_delete::do_deletes (bool from_send_error)
...
@@ -432,23 +440,20 @@ int multi_delete::do_deletes (bool from_send_error)
#endif
/* USE_REGENERATE_TABLE */
#endif
/* USE_REGENERATE_TABLE */
READ_RECORD
info
;
READ_RECORD
info
;
error
=
0
;
init_read_record
(
&
info
,
thd
,
table
,
NULL
,
0
,
0
);
init_read_record
(
&
info
,
thd
,
table
,
NULL
,
0
,
0
);
bool
not_trans_safe
=
some_table_is_not_transaction_safe
(
delete_tables
);
bool
not_trans_safe
=
some_table_is_not_transaction_safe
(
delete_tables
);
while
(
!
(
error
=
info
.
read_record
(
&
info
))
&&
while
(
!
(
error
=
info
.
read_record
(
&
info
))
&&
(
!
thd
->
killed
||
from_send_error
||
not_trans_safe
))
(
!
thd
->
killed
||
from_send_error
||
not_trans_safe
))
{
{
error
=
table
->
file
->
delete_row
(
table
->
record
[
0
]);
if
((
error
=
table
->
file
->
delete_row
(
table
->
record
[
0
])))
if
(
error
)
{
{
table
->
file
->
print_error
(
error
,
MYF
(
0
));
table
->
file
->
print_error
(
error
,
MYF
(
0
));
break
;
break
;
}
}
else
deleted
++
;
deleted
++
;
}
}
end_read_record
(
&
info
);
end_read_record
(
&
info
);
if
(
error
==
-
1
)
if
(
error
==
-
1
)
// End of file
error
=
0
;
error
=
0
;
}
}
return
error
;
return
error
;
...
@@ -464,7 +469,6 @@ bool multi_delete::send_eof()
...
@@ -464,7 +469,6 @@ bool multi_delete::send_eof()
/* reset used flags */
/* reset used flags */
delete_tables
->
table
->
no_keyread
=
0
;
delete_tables
->
table
->
no_keyread
=
0
;
if
(
error
==
-
1
)
error
=
0
;
thd
->
proc_info
=
"end"
;
thd
->
proc_info
=
"end"
;
if
(
error
)
if
(
error
)
{
{
...
@@ -477,22 +481,17 @@ bool multi_delete::send_eof()
...
@@ -477,22 +481,17 @@ bool multi_delete::send_eof()
was a non-transaction-safe table involved, since
was a non-transaction-safe table involved, since
modifications in it cannot be rolled back. */
modifications in it cannot be rolled back. */
if
(
deleted
&&
if
(
deleted
||
some_table_is_not_transaction_safe
(
delete_tables
))
(
!
error
||
some_table_is_not_transaction_safe
(
delete_tables
)))
{
{
mysql_update_log
.
write
(
thd
,
thd
->
query
,
thd
->
query_length
);
mysql_update_log
.
write
(
thd
,
thd
->
query
,
thd
->
query_length
);
Query_log_event
qinfo
(
thd
,
thd
->
query
);
if
(
mysql_bin_log
.
is_open
())
{
/* mysql_bin_log is not open if binlogging or replication
Query_log_event
qinfo
(
thd
,
thd
->
query
);
is not used */
if
(
mysql_bin_log
.
write
(
&
qinfo
)
&&
!
some_table_is_not_transaction_safe
(
delete_tables
))
if
(
mysql_bin_log
.
is_open
()
&&
mysql_bin_log
.
write
(
&
qinfo
)
&&
error
=
1
;
// Log write failed: roll back the SQL statement
!
some_table_is_not_transaction_safe
(
delete_tables
))
}
error
=
1
;
/* Log write failed: roll back
the SQL statement */
/* Commit or rollback the current SQL statement */
/* Commit or rollback the current SQL statement */
VOID
(
ha_autocommit_or_rollback
(
thd
,
error
>
0
));
VOID
(
ha_autocommit_or_rollback
(
thd
,
error
>
0
));
}
}
...
...
sql/sql_parse.cc
View file @
87fd219d
...
@@ -2423,7 +2423,6 @@ mysql_init_query(THD *thd)
...
@@ -2423,7 +2423,6 @@ mysql_init_query(THD *thd)
thd
->
fatal_error
=
0
;
// Safety
thd
->
fatal_error
=
0
;
// Safety
thd
->
last_insert_id_used
=
thd
->
query_start_used
=
thd
->
insert_id_used
=
0
;
thd
->
last_insert_id_used
=
thd
->
query_start_used
=
thd
->
insert_id_used
=
0
;
thd
->
sent_row_count
=
thd
->
examined_row_count
=
0
;
thd
->
sent_row_count
=
thd
->
examined_row_count
=
0
;
thd
->
lex
.
sql_command
=
SQLCOM_SELECT
;
DBUG_VOID_RETURN
;
DBUG_VOID_RETURN
;
}
}
...
@@ -2860,13 +2859,17 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias,
...
@@ -2860,13 +2859,17 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias,
if
(
!
alias
)
/* Alias is case sensitive */
if
(
!
alias
)
/* Alias is case sensitive */
if
(
!
(
alias_str
=
thd
->
memdup
(
alias_str
,
table
->
table
.
length
+
1
)))
if
(
!
(
alias_str
=
thd
->
memdup
(
alias_str
,
table
->
table
.
length
+
1
)))
DBUG_RETURN
(
0
);
DBUG_RETURN
(
0
);
if
(
lower_case_table_names
)
casedn_str
(
table
->
table
.
str
);
if
(
!
(
ptr
=
(
TABLE_LIST
*
)
thd
->
calloc
(
sizeof
(
TABLE_LIST
))))
if
(
!
(
ptr
=
(
TABLE_LIST
*
)
thd
->
calloc
(
sizeof
(
TABLE_LIST
))))
DBUG_RETURN
(
0
);
/* purecov: inspected */
DBUG_RETURN
(
0
);
/* purecov: inspected */
ptr
->
db
=
table
->
db
.
str
?
table
->
db
.
str
:
(
thd
->
db
?
thd
->
db
:
(
char
*
)
""
);
ptr
->
db
=
table
->
db
.
str
?
table
->
db
.
str
:
(
thd
->
db
?
thd
->
db
:
(
char
*
)
""
);
ptr
->
real_name
=
table
->
table
.
str
;
ptr
->
name
=
alias_str
;
ptr
->
name
=
alias_str
;
if
(
lower_case_table_names
)
{
casedn_str
(
ptr
->
db
);
casedn_str
(
table
->
table
.
str
);
}
ptr
->
real_name
=
table
->
table
.
str
;
ptr
->
lock_type
=
flags
;
ptr
->
lock_type
=
flags
;
ptr
->
updating
=
updating
;
ptr
->
updating
=
updating
;
if
(
use_index
)
if
(
use_index
)
...
@@ -2879,7 +2882,8 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias,
...
@@ -2879,7 +2882,8 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias,
/* check that used name is unique */
/* check that used name is unique */
if
(
flags
!=
TL_IGNORE
)
if
(
flags
!=
TL_IGNORE
)
{
{
for
(
TABLE_LIST
*
tables
=
(
TABLE_LIST
*
)
thd
->
lex
.
select
->
table_list
.
first
;
tables
;
for
(
TABLE_LIST
*
tables
=
(
TABLE_LIST
*
)
thd
->
lex
.
select
->
table_list
.
first
;
tables
;
tables
=
tables
->
next
)
tables
=
tables
->
next
)
{
{
if
(
!
strcmp
(
alias_str
,
tables
->
name
)
&&
!
strcmp
(
ptr
->
db
,
tables
->
db
))
if
(
!
strcmp
(
alias_str
,
tables
->
name
)
&&
!
strcmp
(
ptr
->
db
,
tables
->
db
))
...
...
sql/sql_union.cc
View file @
87fd219d
...
@@ -27,7 +27,7 @@
...
@@ -27,7 +27,7 @@
int
mysql_union
(
THD
*
thd
,
LEX
*
lex
,
select_result
*
result
)
int
mysql_union
(
THD
*
thd
,
LEX
*
lex
,
select_result
*
result
)
{
{
SELECT_LEX
*
sl
,
*
last_sl
=
(
SELECT_LEX
*
)
NULL
,
lex_sl
;
SELECT_LEX
*
sl
,
*
last_sl
,
*
lex_sl
;
ORDER
*
order
;
ORDER
*
order
;
List
<
Item
>
item_list
;
List
<
Item
>
item_list
;
TABLE
*
table
;
TABLE
*
table
;
...
@@ -38,7 +38,10 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
...
@@ -38,7 +38,10 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
DBUG_ENTER
(
"mysql_union"
);
DBUG_ENTER
(
"mysql_union"
);
/* Fix tables 'to-be-unioned-from' list to point at opened tables */
/* Fix tables 'to-be-unioned-from' list to point at opened tables */
for
(
sl
=&
lex
->
select_lex
;
sl
&&
sl
->
linkage
!=
NOT_A_SELECT
;
last_sl
=
sl
,
sl
=
sl
->
next
)
last_sl
=
&
lex
->
select_lex
;
for
(
sl
=
last_sl
;
sl
&&
sl
->
linkage
!=
NOT_A_SELECT
;
last_sl
=
sl
,
sl
=
sl
->
next
)
{
{
for
(
TABLE_LIST
*
cursor
=
(
TABLE_LIST
*
)
sl
->
table_list
.
first
;
for
(
TABLE_LIST
*
cursor
=
(
TABLE_LIST
*
)
sl
->
table_list
.
first
;
cursor
;
cursor
;
...
@@ -46,19 +49,27 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
...
@@ -46,19 +49,27 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
cursor
->
table
=
((
TABLE_LIST
*
)
cursor
->
table
)
->
table
;
cursor
->
table
=
((
TABLE_LIST
*
)
cursor
->
table
)
->
table
;
}
}
/* last_sel now points at the last select where the ORDER BY is stored */
if
(
sl
)
if
(
sl
)
{
{
lex_sl
=*
sl
;
/*
sl
=
(
SELECT_LEX
*
)
NULL
;
The found SL is an extra SELECT_LEX argument that contains
if
(
last_sl
)
last_sl
->
next
=
sl
;
the ORDER BY and LIMIT parameter for the whole UNION
*/
lex_sl
=
sl
;
last_sl
->
next
=
0
;
// Remove this extra element
order
=
(
ORDER
*
)
lex_sl
->
order_list
.
first
;
}
else
if
(
!
last_sl
->
braces
)
{
lex_sl
=
last_sl
;
// ORDER BY is here
order
=
(
ORDER
*
)
lex_sl
->
order_list
.
first
;
}
}
else
else
lex_sl
.
linkage
=
UNSPECIFIED_TYPE
;
{
lex_sl
=
0
;
/* Find last select part as it's here ORDER BY and GROUP BY is stored */
order
=
0
;
for
(
last_sl
=
&
lex
->
select_lex
;
}
last_sl
->
next
;
last_sl
=
last_sl
->
next
)
;
if
(
lex
->
select_lex
.
options
&
SELECT_DESCRIBE
)
if
(
lex
->
select_lex
.
options
&
SELECT_DESCRIBE
)
{
{
...
@@ -68,7 +79,8 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
...
@@ -68,7 +79,8 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
res
=
mysql_select
(
thd
,
(
TABLE_LIST
*
)
sl
->
table_list
.
first
,
res
=
mysql_select
(
thd
,
(
TABLE_LIST
*
)
sl
->
table_list
.
first
,
sl
->
item_list
,
sl
->
item_list
,
sl
->
where
,
sl
->
where
,
(
sl
->
braces
)
?
(
ORDER
*
)
sl
->
order_list
.
first
:
(
ORDER
*
)
0
,
((
sl
->
braces
)
?
(
ORDER
*
)
sl
->
order_list
.
first
:
(
ORDER
*
)
0
),
(
ORDER
*
)
sl
->
group_list
.
first
,
(
ORDER
*
)
sl
->
group_list
.
first
,
sl
->
having
,
sl
->
having
,
(
ORDER
*
)
NULL
,
(
ORDER
*
)
NULL
,
...
@@ -79,8 +91,6 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
...
@@ -79,8 +91,6 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
DBUG_RETURN
(
0
);
DBUG_RETURN
(
0
);
}
}
order
=
(
lex_sl
.
linkage
==
UNSPECIFIED_TYPE
)
?
(
(
last_sl
->
braces
)
?
(
ORDER
*
)
0
:
(
ORDER
*
)
last_sl
->
order_list
.
first
)
:
(
ORDER
*
)
lex_sl
.
order_list
.
first
;
{
{
Item
*
item
;
Item
*
item
;
List_iterator
<
Item
>
it
(
lex
->
select_lex
.
item_list
);
List_iterator
<
Item
>
it
(
lex
->
select_lex
.
item_list
);
...
@@ -162,11 +172,11 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
...
@@ -162,11 +172,11 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
}
}
if
(
!
thd
->
fatal_error
)
// Check if EOM
if
(
!
thd
->
fatal_error
)
// Check if EOM
{
{
if
(
lex_sl
.
linkage
==
NOT_A_SELECT
&&
(
lex_sl
.
select_limit
||
lex_sl
.
offset_limit
)
)
if
(
lex_sl
)
{
{
thd
->
offset_limit
=
lex_sl
.
offset_limit
;
thd
->
offset_limit
=
lex_sl
->
offset_limit
;
thd
->
select_limit
=
lex_sl
.
select_limit
+
lex_sl
.
offset_limit
;
thd
->
select_limit
=
lex_sl
->
select_limit
+
lex_sl
->
offset_limit
;
if
(
thd
->
select_limit
<
lex_sl
.
select_limit
)
if
(
thd
->
select_limit
<
lex_sl
->
select_limit
)
thd
->
select_limit
=
HA_POS_ERROR
;
// no limit
thd
->
select_limit
=
HA_POS_ERROR
;
// no limit
if
(
thd
->
select_limit
==
HA_POS_ERROR
)
if
(
thd
->
select_limit
==
HA_POS_ERROR
)
thd
->
options
&=
~
OPTION_FOUND_ROWS
;
thd
->
options
&=
~
OPTION_FOUND_ROWS
;
...
...
sql/sql_yacc.yy
View file @
87fd219d
...
@@ -1348,9 +1348,13 @@ table_to_table:
...
@@ -1348,9 +1348,13 @@ table_to_table:
select:
select:
SELECT_SYM select_part2 { Select->braces=false; } union
select_init { Lex->sql_command=SQLCOM_SELECT; }
select_init:
SELECT_SYM select_part2 { Select->braces=false; } union
|
|
'(' SELECT_SYM select_part2 ')' {Select->braces=true;} union_opt
'(' SELECT_SYM select_part2 ')' { Select->braces=true;} union_opt
select_part2:
select_part2:
{
{
...
@@ -1643,10 +1647,14 @@ simple_expr:
...
@@ -1643,10 +1647,14 @@ simple_expr:
{ $$= new Item_func_decode($3,$5.str); }
{ $$= new Item_func_decode($3,$5.str); }
| ENCODE_SYM '(' expr ',' TEXT_STRING ')'
| ENCODE_SYM '(' expr ',' TEXT_STRING ')'
{ $$= new Item_func_encode($3,$5.str); }
{ $$= new Item_func_encode($3,$5.str); }
| DES_DECRYPT '(' expr ',' expr ')'
| DES_DECRYPT '(' expr ')'
{ $$= new Item_func_des_decrypt($3,$5); }
{ $$= new Item_func_des_decrypt($3); }
| DES_ENCRYPT '(' expr ',' expr ')'
| DES_DECRYPT '(' expr ',' expr ')'
{ $$= new Item_func_des_encrypt($3,$5); }
{ $$= new Item_func_des_decrypt($3,$5); }
| DES_ENCRYPT '(' expr ')'
{ $$= new Item_func_des_encrypt($3); }
| DES_ENCRYPT '(' expr ',' expr ')'
{ $$= new Item_func_des_encrypt($3,$5); }
| EXPORT_SET '(' expr ',' expr ',' expr ')'
| EXPORT_SET '(' expr ',' expr ',' expr ')'
{ $$= new Item_func_export_set($3, $5, $7); }
{ $$= new Item_func_export_set($3, $5, $7); }
| EXPORT_SET '(' expr ',' expr ',' expr ',' expr ')'
| EXPORT_SET '(' expr ',' expr ',' expr ',' expr ')'
...
@@ -3573,12 +3581,12 @@ union_list:
...
@@ -3573,12 +3581,12 @@ union_list:
net_printf(&lex->thd->net, ER_WRONG_USAGE,"UNION","INTO");
net_printf(&lex->thd->net, ER_WRONG_USAGE,"UNION","INTO");
YYABORT;
YYABORT;
}
}
if (lex->select->linkage
==
NOT_A_SELECT)
if (lex->select->linkage
==
NOT_A_SELECT)
YYABORT;
YYABORT;
mysql_new_select(lex);
mysql_new_select(lex);
lex->select->linkage=UNION_TYPE;
lex->select->linkage=UNION_TYPE;
}
}
select
select
_init
union_opt:
union_opt:
union {}
union {}
...
...
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