mirror of
https://github.com/MariaDB/server.git
synced 2025-01-17 04:22:27 +01:00
Fixed sleep time in mysql-test-run
Fixed bug in query cache. Cleaned up des_crypt code.
This commit is contained in:
parent
8bef3771f4
commit
87fd219d67
24 changed files with 829 additions and 385 deletions
|
@ -11282,7 +11282,7 @@ mysql> SELECT name, birth, death,
|
|||
+--------+------------+------------+------+
|
||||
@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.
|
||||
@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.
|
|||
Conceptually, @code{NULL} means missing value or unknown value and it
|
||||
is treated somewhat differently than other values. To test for @code{NULL},
|
||||
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
|
||||
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 |
|
||||
+----------+-----------+----------+----------+
|
||||
|
@ -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
|
||||
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
|
||||
|
@ -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
|
||||
zero characters). In MySQL, SQL patterns are case insensitive by
|
||||
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.
|
||||
|
||||
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}.
|
|||
|
||||
@itemize @bullet
|
||||
@item
|
||||
Fixed problem with @code{GRANT} when using @code{lower_case_table_names == 1}.
|
||||
@item
|
||||
Changed @code{SELECT ... IN SHARE MODE} to
|
||||
@code{SELECT .. LOCK IN SHARE MODE} (as in MySQL 3.23).
|
||||
@item
|
||||
|
|
|
@ -46,7 +46,7 @@ which ()
|
|||
sleep_until_file_deleted ()
|
||||
{
|
||||
file=$1
|
||||
loop=$SLEEP_TIME
|
||||
loop=$SLEEP_TIME_FOR_DELETE
|
||||
while (test $loop -gt 0)
|
||||
do
|
||||
sleep 1
|
||||
|
@ -61,7 +61,8 @@ sleep_until_file_deleted ()
|
|||
sleep_until_file_exists ()
|
||||
{
|
||||
file=$1
|
||||
loop=60 # Should be long enough enough for all cases
|
||||
loop=$2
|
||||
org_time=$2
|
||||
while (test $loop -gt 0)
|
||||
do
|
||||
sleep 1
|
||||
|
@ -71,7 +72,7 @@ sleep_until_file_exists ()
|
|||
fi
|
||||
loop=`expr $loop - 1`
|
||||
done
|
||||
echo "ERROR: $file was not created in 60 seconds; Aborting"
|
||||
echo "ERROR: $file was not created in $org_time seconds; Aborting"
|
||||
exit 1;
|
||||
}
|
||||
|
||||
|
@ -172,7 +173,11 @@ DO_GCOV=""
|
|||
DO_GDB=""
|
||||
DO_DDD=""
|
||||
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
|
||||
DBUSER=""
|
||||
START_WAIT_TIMEOUT=3
|
||||
|
@ -235,7 +240,6 @@ while test $# -gt 0; do
|
|||
EXTRA_MYSQL_TEST_OPT="$EXTRA_MYSQL_TEST_OPT $1" ;;
|
||||
--sleep=*)
|
||||
EXTRA_MYSQL_TEST_OPT="$EXTRA_MYSQL_TEST_OPT $1"
|
||||
SLEEP_TIME=`$ECHO "$1" | $SED -e "s;--sleep=;;"`
|
||||
;;
|
||||
--mysqld=*)
|
||||
TMP=`$ECHO "$1" | $SED -e "s;--mysqld=;;"`
|
||||
|
@ -260,8 +264,9 @@ while test $# -gt 0; do
|
|||
fi
|
||||
DO_GDB=1
|
||||
# We must use manager, as things doesn't work on Linux without it
|
||||
USE_MANAGER=1
|
||||
USE_RUNNING_SERVER=""
|
||||
# This needs to be checked properly
|
||||
# USE_MANAGER=1
|
||||
# USE_RUNNING_SERVER=""
|
||||
;;
|
||||
--client-gdb )
|
||||
if [ x$BINARY_DIST = x1 ] ; then
|
||||
|
@ -755,7 +760,8 @@ EOF
|
|||
else
|
||||
manager_launch master $MYSQLD $master_args
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -847,7 +853,8 @@ start_slave()
|
|||
manager_launch $slave_ident $SLAVE_MYSQLD $slave_args
|
||||
fi
|
||||
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 ()
|
||||
|
@ -1143,6 +1150,8 @@ then
|
|||
# Remove files that can cause problems
|
||||
$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"
|
||||
mysql_install_db
|
||||
start_manager
|
||||
|
|
|
@ -216,3 +216,50 @@ select 1+1,"a",count(*) from t1 where foo in (2);
|
|||
1+1 a count(*)
|
||||
2 a 0
|
||||
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;
|
||||
|
|
15
mysql-test/r/innodb_cache.result
Normal file
15
mysql-test/r/innodb_cache.result
Normal file
|
@ -0,0 +1,15 @@
|
|||
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;
|
|
@ -1,3 +1,5 @@
|
|||
flush query cache;
|
||||
flush query cache;
|
||||
reset query cache;
|
||||
flush status;
|
||||
drop table if exists t1,t2,t3;
|
||||
|
@ -148,20 +150,6 @@ show status like "Qcache_queries_in_cache";
|
|||
Variable_name Value
|
||||
Qcache_queries_in_cache 0
|
||||
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);
|
||||
insert into t1 values (1),(2),(3);
|
||||
create table t2 (a int not null);
|
||||
|
|
|
@ -74,6 +74,14 @@ a b
|
|||
2 b
|
||||
3 c
|
||||
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;
|
||||
table type possible_keys key key_len ref rows Extra
|
||||
t1 ALL NULL NULL NULL NULL 4
|
||||
|
|
|
@ -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(concat(lcase(concat('THIS',' ','IS',' ','A',' ')),ucase('false'),' ','test'),'FALSE','REAL') ;
|
||||
select soundex(''),soundex('he'),soundex('hello all folks');
|
||||
--replace_result $1$aa$4OSUA5cjdx0RUQ08opV27/ aaqPiZY5xR5l.
|
||||
select password('test'),length(encrypt('test')),encrypt('test','aa');
|
||||
select md5('hello');
|
||||
select repeat('monty',5),concat('*',space(5),'*');
|
||||
|
|
1
mysql-test/t/innodb_cache-master.opt
Normal file
1
mysql-test/t/innodb_cache-master.opt
Normal file
|
@ -0,0 +1 @@
|
|||
--set-variable=query_cache_size=1M
|
14
mysql-test/t/innodb_cache.test
Normal file
14
mysql-test/t/innodb_cache.test
Normal file
|
@ -0,0 +1,14 @@
|
|||
-- 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;
|
|
@ -1,11 +1,11 @@
|
|||
-- source include/have_innodb.inc
|
||||
|
||||
#
|
||||
# Tests with query cache
|
||||
#
|
||||
|
||||
# Reset query cache variables.
|
||||
|
||||
flush query cache; # This crashed in some versions
|
||||
flush query cache; # This crashed in some versions
|
||||
reset query cache;
|
||||
flush status;
|
||||
drop table if exists t1,t2,t3;
|
||||
|
@ -73,17 +73,6 @@ delete from t3 where a=10;
|
|||
show status like "Qcache_queries_in_cache";
|
||||
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
|
||||
#
|
||||
create table t1 (a int not null);
|
||||
|
|
|
@ -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
|
||||
(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
|
||||
explain select a,b from t1 union all select a,b from t2;
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
* Module: my_semaphore.c (Original: semaphore.c from pthreads library)
|
||||
*
|
||||
* Purpose:
|
||||
* Semaphores aren't actually part of the PThreads standard.
|
||||
* They are defined by the POSIX Standard:
|
||||
* Semaphores aren't actually part of the PThreads standard.
|
||||
* They are defined by the POSIX Standard:
|
||||
*
|
||||
* POSIX 1003.1b-1993 (POSIX.1b)
|
||||
* POSIX 1003.1b-1993 (POSIX.1b)
|
||||
*
|
||||
* -------------------------------------------------------------
|
||||
*
|
||||
|
@ -52,33 +52,27 @@
|
|||
DOCPUBLIC
|
||||
This function initializes an unnamed semaphore. the
|
||||
initial value of the semaphore is 'value'
|
||||
|
||||
|
||||
PARAMETERS
|
||||
sem
|
||||
pointer to an instance of sem_t
|
||||
|
||||
pshared
|
||||
if zero, this semaphore may only be shared between
|
||||
threads in the same process.
|
||||
if nonzero, the semaphore can be shared between
|
||||
processes
|
||||
|
||||
value
|
||||
initial value of the semaphore counter
|
||||
|
||||
DESCRIPTION
|
||||
This function initializes an unnamed semaphore. The
|
||||
initial value of the semaphore is set to 'value'.
|
||||
|
||||
sem Pointer to an instance of sem_t
|
||||
|
||||
pshared If zero, this semaphore may only be shared between
|
||||
threads in the same process.
|
||||
If nonzero, the semaphore can be shared between
|
||||
processes
|
||||
|
||||
value Initial value of the semaphore counter
|
||||
|
||||
RESULTS
|
||||
0 successfully created semaphore,
|
||||
-1 failed, error in errno
|
||||
0 Successfully created semaphore,
|
||||
-1 Failed, error in errno
|
||||
|
||||
ERRNO
|
||||
EINVAL 'sem' is not a valid semaphore,
|
||||
ENOSPC a required resource has been exhausted,
|
||||
ENOSYS semaphores are not supported,
|
||||
EPERM the process lacks appropriate privilege
|
||||
|
||||
EINVAL 'sem' is not a valid semaphore,
|
||||
ENOSPC A required resource has been exhausted,
|
||||
ENOSYS Semaphores are not supported,
|
||||
EPERM The process lacks appropriate privilege
|
||||
|
||||
*/
|
||||
|
||||
int
|
||||
|
@ -111,10 +105,10 @@ sem_init (sem_t *sem, int pshared, unsigned int value)
|
|||
InitializeCriticalSection(&sem->sem_lock_cs);
|
||||
}
|
||||
#else /* HAVE_CREATESEMAPHORE */
|
||||
*sem = CreateSemaphore (NULL, /* Always NULL */
|
||||
value, /* Initial value */
|
||||
*sem = CreateSemaphore (NULL, /* Always NULL */
|
||||
value, /* Initial value */
|
||||
0x7FFFFFFFL, /* Maximum value */
|
||||
NULL); /* Name */
|
||||
NULL); /* Name */
|
||||
if (!*sem)
|
||||
result = ENOSPC;
|
||||
#endif /* HAVE_CREATESEMAPHORE */
|
||||
|
@ -133,20 +127,15 @@ sem_init (sem_t *sem, int pshared, unsigned int value)
|
|||
This function destroys an unnamed semaphore.
|
||||
|
||||
PARAMETERS
|
||||
sem
|
||||
pointer to an instance of sem_t
|
||||
|
||||
DESCRIPTION
|
||||
This function destroys an unnamed semaphore.
|
||||
sem Pointer to an instance of sem_t
|
||||
|
||||
RESULTS
|
||||
0 successfully destroyed semaphore,
|
||||
-1 failed, error in errno
|
||||
0 Successfully destroyed semaphore,
|
||||
-1 Failed, error in errno
|
||||
ERRNO
|
||||
EINVAL 'sem' is not a valid semaphore,
|
||||
ENOSYS semaphores are not supported,
|
||||
EBUSY threads (or processes) are currently
|
||||
blocked on 'sem'
|
||||
EINVAL 'sem' is not a valid semaphore,
|
||||
ENOSYS Semaphores are not supported,
|
||||
EBUSY Threads (or processes) are currently blocked on 'sem'
|
||||
*/
|
||||
|
||||
int
|
||||
|
@ -154,7 +143,7 @@ sem_destroy (sem_t * sem)
|
|||
{
|
||||
int result = 0;
|
||||
|
||||
#ifdef EXTRA_DEBUG
|
||||
#ifdef EXTRA_DEBUG
|
||||
if (sem == NULL || *sem == NULL)
|
||||
{
|
||||
errno=EINVAL;
|
||||
|
@ -183,27 +172,24 @@ sem_destroy (sem_t * sem)
|
|||
|
||||
/*
|
||||
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
|
||||
semaphore value is greater than zero, it decreases
|
||||
its value by one. If the semaphore value is zero, then
|
||||
this function returns immediately with the error EAGAIN
|
||||
|
||||
PARAMETERS
|
||||
sem Pointer to an instance of sem_t
|
||||
|
||||
RESULTS
|
||||
0 successfully decreased semaphore,
|
||||
-1 failed, error in errno
|
||||
0 Successfully decreased semaphore,
|
||||
-1 Failed, error in errno
|
||||
|
||||
ERRNO
|
||||
EAGAIN the semaphore was already locked,
|
||||
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.
|
||||
EAGAIN The semaphore was already locked,
|
||||
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
|
||||
|
@ -214,7 +200,7 @@ sem_trywait(sem_t * sem)
|
|||
int errno = EINVAL;
|
||||
return -1;
|
||||
#else /* HAVE_CREATESEMAPHORE */
|
||||
#ifdef EXTRA_DEBUG
|
||||
#ifdef EXTRA_DEBUG
|
||||
if (sem == NULL || *sem == NULL)
|
||||
{
|
||||
errno=EINVAL;
|
||||
|
@ -234,7 +220,7 @@ sem_trywait(sem_t * sem)
|
|||
|
||||
#ifndef HAVE_CREATESEMAPHORE
|
||||
|
||||
static void
|
||||
static void
|
||||
ptw32_decrease_semaphore(sem_t * sem)
|
||||
{
|
||||
EnterCriticalSection(&sem->sem_lock_cs);
|
||||
|
@ -267,13 +253,6 @@ ptw32_increase_semaphore(sem_t * sem, unsigned int n)
|
|||
/*
|
||||
------------------------------------------------------
|
||||
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
|
||||
semaphore value is greater than zero, it decreases
|
||||
its value by one. If the semaphore value is zero, then
|
||||
|
@ -281,15 +260,18 @@ ptw32_increase_semaphore(sem_t * sem, unsigned int n)
|
|||
successfully decrease the value or until interrupted by
|
||||
a signal.
|
||||
|
||||
RESULTS
|
||||
0 successfully decreased semaphore,
|
||||
-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.
|
||||
PARAMETERS
|
||||
sem Pointer to an instance of sem_t
|
||||
|
||||
RESULTS
|
||||
0 Successfully decreased semaphore,
|
||||
-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.
|
||||
*/
|
||||
|
||||
int
|
||||
|
@ -297,7 +279,7 @@ sem_wait(sem_t *sem)
|
|||
{
|
||||
int result;
|
||||
|
||||
#ifdef EXTRA_DEBUG
|
||||
#ifdef EXTRA_DEBUG
|
||||
if (sem == NULL || *sem == NULL)
|
||||
{
|
||||
errno=EINVAL;
|
||||
|
@ -331,30 +313,27 @@ sem_wait(sem_t *sem)
|
|||
/*
|
||||
------------------------------------------------------
|
||||
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
|
||||
are waiting threads (or processes), one is awakened;
|
||||
otherwise, the semaphore value is incremented by one.
|
||||
|
||||
PARAMETERS
|
||||
sem Pointer to an instance of sem_t
|
||||
|
||||
RESULTS
|
||||
0 successfully posted semaphore,
|
||||
-1 failed, error in errno
|
||||
0 Successfully posted semaphore,
|
||||
-1 Failed, error in errno
|
||||
|
||||
ERRNO
|
||||
EINVAL 'sem' is not a valid semaphore,
|
||||
ENOSYS semaphores are not supported,
|
||||
EINVAL 'sem' is not a valid semaphore,
|
||||
ENOSYS Semaphores are not supported,
|
||||
|
||||
*/
|
||||
|
||||
int
|
||||
sem_post (sem_t * sem)
|
||||
{
|
||||
#ifdef EXTRA_DEBUG
|
||||
#ifdef EXTRA_DEBUG
|
||||
if (sem == NULL || *sem == NULL)
|
||||
{
|
||||
errno=EINVAL;
|
||||
|
@ -378,32 +357,27 @@ sem_post (sem_t * sem)
|
|||
/*
|
||||
------------------------------------------------------
|
||||
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
|
||||
are waiting threads (or processes), n <= count are awakened;
|
||||
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
|
||||
0 successfully posted semaphore,
|
||||
-1 failed, error in errno
|
||||
0 Successfully posted semaphore,
|
||||
-1 Failed, error in errno
|
||||
|
||||
ERRNO
|
||||
EINVAL 'sem' is not a valid semaphore
|
||||
or count is less than or equal to zero.
|
||||
EINVAL 'sem' is not a valid semaphore or count is less
|
||||
than or equal to zero.
|
||||
*/
|
||||
|
||||
int
|
||||
sem_post_multiple (sem_t * sem, int count )
|
||||
{
|
||||
#ifdef EXTRA_DEBUG
|
||||
#ifdef EXTRA_DEBUG
|
||||
if (sem == NULL || *sem == NULL || count <= 0)
|
||||
{
|
||||
errno=EINVAL;
|
||||
|
|
|
@ -15,72 +15,80 @@
|
|||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include <mysql_priv.h>
|
||||
#include <m_ctype.h>
|
||||
|
||||
#ifdef HAVE_OPENSSL
|
||||
|
||||
/*
|
||||
Function which loads DES keys from plaintext file
|
||||
into memory on MySQL server startup and on command
|
||||
FLUSH DES_KEYS. Blame tonu@spam.ee on bugs ;)
|
||||
Function which loads DES keys from plaintext file into memory on MySQL
|
||||
server startup and on command 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)
|
||||
{
|
||||
FILE *file;
|
||||
int ret=0;
|
||||
char offset;
|
||||
char buf[1024];
|
||||
File file;
|
||||
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");
|
||||
VOID(pthread_mutex_lock(&LOCK_open));
|
||||
DBUG_PRINT("enter",("name: %s",file_name));
|
||||
if (!(file=my_fopen(file_name,O_RDONLY,MYF(MY_WME))))
|
||||
|
||||
VOID(pthread_mutex_lock(&LOCK_open));
|
||||
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)))
|
||||
goto error;
|
||||
|
||||
bzero((char*) des_keyschedule,sizeof(struct st_des_keyschedule) * 10);
|
||||
default_des_key=15; // Impossible key
|
||||
for (;;)
|
||||
{
|
||||
goto error_noclose;
|
||||
}
|
||||
while(!feof(file))
|
||||
{
|
||||
if ((my_fread(file, &offset, 1, MY_WME)) != 1)
|
||||
goto error_close;
|
||||
fgets(buf,sizeof(buf),file);
|
||||
int len=strlen(buf);
|
||||
if (len-->=1)
|
||||
buf[len]='\0';
|
||||
/* We make good 24-byte (168 bit) key from given plaintext key with MD5 */
|
||||
offset-='0';
|
||||
if (offset >= 0 && offset <=9)
|
||||
char *start, *end;
|
||||
char buf[1024];
|
||||
st_des_keyblock keyblock;
|
||||
uint length;
|
||||
|
||||
if (!(length=my_b_gets(&io,buf,sizeof(buf)-1)))
|
||||
break; // End of file
|
||||
offset=buf[0];
|
||||
if (offset >= '0' && offset <= '9') // If ok key
|
||||
{
|
||||
EVP_BytesToKey(EVP_des_ede3_cbc(),EVP_md5(),NULL,
|
||||
(uchar *)buf,
|
||||
strlen(buf),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);
|
||||
}
|
||||
offset=(char) (offset - '0');
|
||||
// Remove newline and possible other control characters
|
||||
for (start=buf+1 ; isspace(*start) ; start++) ;
|
||||
end=buf+length;
|
||||
for (end=strend(buf) ; end > start && iscntrl(end[-1]) ; end--) ;
|
||||
|
||||
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
|
||||
{
|
||||
DBUG_PRINT("des",("wrong offset: %d",offset));
|
||||
DBUG_PRINT("des",("wrong offset: %c",offset));
|
||||
}
|
||||
}
|
||||
error_close:
|
||||
(void) my_fclose(file,MYF(MY_WME));
|
||||
error_noclose:
|
||||
|
||||
error:
|
||||
if (file >= 0)
|
||||
{
|
||||
my_close(file,MYF(0));
|
||||
end_io_cache(&io);
|
||||
}
|
||||
VOID(pthread_mutex_unlock(&LOCK_open));
|
||||
/* if (ret)
|
||||
do something; */
|
||||
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 */
|
||||
|
||||
|
|
|
@ -75,7 +75,11 @@ String *Item_func_md5::val_str(String *str)
|
|||
my_MD5Init (&context);
|
||||
my_MD5Update (&context,(unsigned char *) sptr->ptr(), sptr->length());
|
||||
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(),
|
||||
"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
||||
digest[0], digest[1], digest[2], digest[3],
|
||||
|
@ -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
|
||||
Works only if compiled with OpenSSL library support.
|
||||
Output always starts with magic char "1" and all
|
||||
encrypted output is encoded into ASCII-protected
|
||||
container.
|
||||
Original input is returned as output if input string
|
||||
begins with magic "1". Credit card number always begin
|
||||
with 4,5 or 6.
|
||||
Function des_encrypt() by tonu@spam.ee & monty
|
||||
Works only if compiled with OpenSSL library support.
|
||||
This returns a binary string where first character is
|
||||
CHAR(128 | tail-length << 4 | key-number).
|
||||
If one uses a string key key_number is 0.
|
||||
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 *res =args[0]->val_str(str);
|
||||
#ifdef HAVE_OPENSSL
|
||||
des_cblock ivec={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
|
||||
struct st_des_keyblock keyblock;
|
||||
struct st_des_keyschedule 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))
|
||||
return 0;
|
||||
if (res->length() == 0)
|
||||
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);
|
||||
for(uint i=0 ; i < str->length() ; ++i)
|
||||
{
|
||||
res->append(bin_to_ascii((uchar)str->c_ptr()[i] & 0x3f));
|
||||
res->append(bin_to_ascii(((uchar)str->c_ptr()[i] >> 5 ) & 0x3f));
|
||||
}
|
||||
if (arg_count == 1)
|
||||
keyschedule_ptr=des_keyschedule[key_number=default_des_key];
|
||||
else if (args[1]->result_type == INT_RESULT)
|
||||
{
|
||||
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;
|
||||
return 0;
|
||||
#endif /* HAVE_OPENSSL */
|
||||
}
|
||||
|
||||
|
||||
String *Item_func_des_decrypt::val_str(String *str)
|
||||
{
|
||||
String *res =args[0]->val_str(str);
|
||||
#ifdef HAVE_OPENSSL
|
||||
des_key_schedule ks1, ks2, ks3;
|
||||
des_cblock ivec={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
|
||||
struct st_des_keyblock keyblock;
|
||||
struct st_des_keyschedule keyschedule;
|
||||
struct st_des_keyschedule *keyschedule_ptr=&keyschedule;
|
||||
String *res= args[0]->val_str(str);
|
||||
|
||||
if ((null_value=args[0]->null_value))
|
||||
return 0;
|
||||
if (res->length() == 0)
|
||||
return &empty_string;
|
||||
if (res->length(0) < 9 || (res->length()) % 8 != 1 || !(res->[0] & 128))
|
||||
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);
|
||||
for(uint i=1 ; i < res->length() ; i+=2)
|
||||
{
|
||||
str->append((ascii_to_bin(res->c_ptr()[i]))
|
||||
| (ascii_to_bin(res->c_ptr()[i+1]) << 5 ));
|
||||
}
|
||||
|
||||
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)
|
||||
uint key_number=res->[0] & 15;
|
||||
// Check if automatic key and that we have privilege to uncompress using it
|
||||
if (!(current_thd->master_access & PROCESS_ACL) || key_number > 9)
|
||||
goto error;
|
||||
keyschedule_ptr=des_keyschedule[key_number-1];
|
||||
}
|
||||
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;
|
||||
return 0;
|
||||
#endif /* HAVE_OPENSSL */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** concat with separator. First arg is the separator
|
||||
** concat_ws takes at least two arguments.
|
||||
concat with separator. First arg is the separator
|
||||
concat_ws takes at least two arguments.
|
||||
*/
|
||||
|
||||
String *Item_func_concat_ws::val_str(String *str)
|
||||
|
@ -1146,6 +1138,7 @@ String *Item_func_password::val_str(String *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)
|
||||
{
|
||||
|
|
|
@ -228,9 +228,9 @@ class Item_func_des_encrypt :public Item_str_func
|
|||
public:
|
||||
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 *c): Item_str_func(a,b,c) {}
|
||||
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"; }
|
||||
};
|
||||
|
||||
|
@ -240,7 +240,6 @@ class Item_func_des_decrypt :public Item_str_func
|
|||
public:
|
||||
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 *c): Item_str_func(a,b,c) {}
|
||||
String *val_str(String *);
|
||||
void fix_length_and_dec() { maybe_null=1; max_length = args[0]->max_length; }
|
||||
const char *func_name() const { return "des_decrypt"; }
|
||||
|
|
|
@ -405,9 +405,9 @@ struct st_des_keyschedule
|
|||
{
|
||||
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);
|
||||
struct st_des_keyschedule * des_key(int);
|
||||
#endif /* HAVE_OPENSSL */
|
||||
|
||||
/* sql_list.c */
|
||||
|
|
|
@ -243,7 +243,6 @@ static char glob_hostname[FN_REFLEN];
|
|||
#include "sslopt-vars.h"
|
||||
#ifdef HAVE_OPENSSL
|
||||
static char * des_key_file = 0;
|
||||
struct st_des_keyschedule des_keyschedule[10];
|
||||
struct st_VioSSLAcceptorFd * ssl_acceptor_fd = 0;
|
||||
#endif /* HAVE_OPENSSL */
|
||||
|
||||
|
@ -1751,8 +1750,6 @@ int main(int argc, char **argv)
|
|||
opt_use_ssl = 0;
|
||||
/* 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)
|
||||
load_des_key_file(des_key_file);
|
||||
#endif /* HAVE_OPENSSL */
|
||||
|
|
|
@ -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;
|
||||
db_access=0; host_access= ~0;
|
||||
char key[ACL_KEY_LENGTH],*end;
|
||||
char key[ACL_KEY_LENGTH],*tmp_db,*end;
|
||||
acl_entry *entry;
|
||||
|
||||
VOID(pthread_mutex_lock(&acl_cache->lock));
|
||||
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);
|
||||
if ((entry=(acl_entry*) acl_cache->search(key,key_length)))
|
||||
{
|
||||
|
@ -1377,6 +1382,11 @@ public:
|
|||
db = strdup_root(&memex,d);
|
||||
user = strdup_root(&memex,u);
|
||||
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;
|
||||
hash_key = (char*) alloc_root(&memex,key_length);
|
||||
strmov(strmov(strmov(hash_key,user)+1,db)+1,tname);
|
||||
|
@ -1398,7 +1408,13 @@ public:
|
|||
privs = cols = 0; /* 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);
|
||||
strmov(strmov(strmov(hash_key,user)+1,db)+1,tname);
|
||||
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,
|
|||
{
|
||||
List_iterator <LEX_USER> str_list (list);
|
||||
LEX_USER *Str;
|
||||
char what;
|
||||
char what,tmp_db[NAME_LEN+1];
|
||||
bool create_new_users=0;
|
||||
TABLE_LIST tables[2];
|
||||
DBUG_ENTER("mysql_grant");
|
||||
|
@ -2002,6 +2018,12 @@ int mysql_grant (THD *thd, const char *db, List <LEX_USER> &list, uint rights,
|
|||
}
|
||||
|
||||
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 */
|
||||
|
||||
|
@ -2220,8 +2242,8 @@ bool check_grant(THD *thd, uint want_access, TABLE_LIST *tables,
|
|||
table->grant.want_privilege=0;
|
||||
continue; // Already checked
|
||||
}
|
||||
const char *db = table->db ? table->db : thd->db;
|
||||
GRANT_TABLE *grant_table = table_hash_search(thd->host,thd->ip,db,user,
|
||||
GRANT_TABLE *grant_table = table_hash_search(thd->host,thd->ip,
|
||||
table->db,user,
|
||||
table->real_name,0);
|
||||
if (!grant_table)
|
||||
{
|
||||
|
|
372
sql/sql_cache.cc
372
sql/sql_cache.cc
|
@ -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
|
||||
(more small blocks needed frequently then bigger one).
|
||||
|
||||
6. Packing cache.
|
||||
7. Packing cache.
|
||||
|
||||
Query cache packing is divided into two operation:
|
||||
- pack_cache
|
||||
|
@ -305,7 +305,8 @@ If join_results allocated new block(s) then we need call pack_cache again.
|
|||
#define BLOCK_UNLOCK_RD(B) { \
|
||||
DBUG_PRINT("lock", ("%d UNLOCK_RD 0x%lx",\
|
||||
__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
|
||||
#define MUTEX_LOCK(M) pthread_mutex_lock(M)
|
||||
#define MUTEX_UNLOCK(M) pthread_mutex_unlock(M)
|
||||
|
@ -581,6 +582,7 @@ void query_cache_insert(NET *net, const char *packet, ulong length)
|
|||
else
|
||||
STRUCT_UNLOCK(&query_cache.structure_guard_mutex);
|
||||
}
|
||||
DBUG_EXECUTE("check_querycache",query_cache.check_integrity(););
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
@ -609,6 +611,7 @@ void query_cache_abort(NET *net)
|
|||
}
|
||||
STRUCT_UNLOCK(&query_cache.structure_guard_mutex);
|
||||
}
|
||||
DBUG_EXECUTE("check_querycache",query_cache.check_integrity(););
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
@ -656,12 +659,14 @@ void query_cache_end_of_result(NET *net)
|
|||
}
|
||||
net->query_cache_query=0;
|
||||
}
|
||||
DBUG_EXECUTE("check_querycache",query_cache.check_integrity(););
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
void query_cache_invalidate_by_MyISAM_filename(const char *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)
|
|||
if (bins[0].free_blocks == 0)
|
||||
{
|
||||
wreck(__LINE__,"no free memory found in (bins[0].free_blocks");
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1335,12 +1341,13 @@ void Query_cache::free_cache(my_bool destruction)
|
|||
hash_free(&tables);
|
||||
if (!destruction)
|
||||
STRUCT_UNLOCK(&structure_guard_mutex);
|
||||
DBUG_EXECUTE("check_querycache",check_integrity(););
|
||||
}
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
Free block data
|
||||
Free block data
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
|
@ -1501,7 +1508,6 @@ Query_cache::append_result_data(Query_cache_block **current_block,
|
|||
DBUG_PRINT("qcache", ("size limit reached %lu > %lu",
|
||||
query_block->query()->length(),
|
||||
query_cache_limit));
|
||||
*current_block=0; // Mark error
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
if (*current_block == 0)
|
||||
|
@ -1550,8 +1556,8 @@ Query_cache::append_result_data(Query_cache_block **current_block,
|
|||
query_block,
|
||||
Query_cache_block::RES_CONT);
|
||||
/*
|
||||
new_block may be not 0 even !success (if write_result_data
|
||||
allocate small block but failed allocate continue
|
||||
new_block may be != 0 even !success (if write_result_data
|
||||
allocate a small block but failed to allocate continue)
|
||||
*/
|
||||
if (new_block != 0)
|
||||
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)
|
|||
|
||||
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;
|
||||
DBUG_PRINT("qcache",("first_block 0x%lx, block 0x%lx, pnext 0x%lx pprev 0x%lx",
|
||||
(ulong) first_block, (ulong) block,block->pnext,
|
||||
|
@ -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,
|
||||
add_size));
|
||||
|
||||
if (next_block->is_free())
|
||||
if (next_block != first_block && next_block->is_free())
|
||||
{
|
||||
ulong old_len = block->length;
|
||||
exclude_from_free_memory_list(next_block);
|
||||
|
@ -2404,7 +2410,7 @@ my_bool Query_cache::move_by_type(byte **border,
|
|||
char *data = (char*) block->data();
|
||||
byte *key;
|
||||
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);
|
||||
|
||||
block->destroy();
|
||||
|
@ -2452,7 +2458,7 @@ my_bool Query_cache::move_by_type(byte **border,
|
|||
block->data())->result();
|
||||
byte *key;
|
||||
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);
|
||||
|
||||
memcpy((char*) new_block->table(0), (char*) block->table(0),
|
||||
|
@ -2682,8 +2688,9 @@ void Query_cache::wreck(uint line, const char *message)
|
|||
DBUG_PRINT("warning", ("=================================="));
|
||||
if (thd)
|
||||
thd->killed = 1;
|
||||
bins_dump();
|
||||
cache_dump();
|
||||
/* check_integrity(); */ /* Can't call it here because of locks */
|
||||
bins_dump();
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
@ -2821,4 +2828,347 @@ void Query_cache::tables_dump()
|
|||
}
|
||||
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 */
|
||||
|
|
|
@ -379,6 +379,10 @@ protected:
|
|||
void cache_dump();
|
||||
void queries_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
|
||||
friend void query_cache_insert(NET *net, const char *packet, ulong length);
|
||||
friend void query_cache_end_of_result(NET *net);
|
||||
|
|
|
@ -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 error = 0, counter = 0;
|
||||
|
@ -420,7 +427,8 @@ int multi_delete::do_deletes (bool from_send_error)
|
|||
{
|
||||
TABLE_LIST 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.grant=table->grant;
|
||||
table_list.db = table_being_deleted->db;
|
||||
|
@ -432,23 +440,20 @@ int multi_delete::do_deletes (bool from_send_error)
|
|||
#endif /* USE_REGENERATE_TABLE */
|
||||
|
||||
READ_RECORD info;
|
||||
error=0;
|
||||
init_read_record(&info,thd,table,NULL,0,0);
|
||||
bool not_trans_safe = some_table_is_not_transaction_safe(delete_tables);
|
||||
while (!(error=info.read_record(&info)) &&
|
||||
(!thd->killed || from_send_error || not_trans_safe))
|
||||
{
|
||||
error=table->file->delete_row(table->record[0]);
|
||||
if (error)
|
||||
if ((error=table->file->delete_row(table->record[0])))
|
||||
{
|
||||
table->file->print_error(error,MYF(0));
|
||||
break;
|
||||
}
|
||||
else
|
||||
deleted++;
|
||||
deleted++;
|
||||
}
|
||||
end_read_record(&info);
|
||||
if (error == -1)
|
||||
if (error == -1) // End of file
|
||||
error = 0;
|
||||
}
|
||||
return error;
|
||||
|
@ -464,7 +469,6 @@ bool multi_delete::send_eof()
|
|||
|
||||
/* reset used flags */
|
||||
delete_tables->table->no_keyread=0;
|
||||
if (error == -1) error = 0;
|
||||
thd->proc_info="end";
|
||||
if (error)
|
||||
{
|
||||
|
@ -477,22 +481,17 @@ bool multi_delete::send_eof()
|
|||
was a non-transaction-safe table involved, since
|
||||
modifications in it cannot be rolled back. */
|
||||
|
||||
if (deleted &&
|
||||
(!error || some_table_is_not_transaction_safe(delete_tables)))
|
||||
if (deleted || some_table_is_not_transaction_safe(delete_tables))
|
||||
{
|
||||
mysql_update_log.write(thd,thd->query,thd->query_length);
|
||||
Query_log_event qinfo(thd, thd->query);
|
||||
|
||||
/* mysql_bin_log is not open if binlogging or replication
|
||||
is not used */
|
||||
|
||||
if (mysql_bin_log.is_open() && mysql_bin_log.write(&qinfo) &&
|
||||
!some_table_is_not_transaction_safe(delete_tables))
|
||||
error=1; /* Log write failed: roll back
|
||||
the SQL statement */
|
||||
|
||||
if (mysql_bin_log.is_open())
|
||||
{
|
||||
Query_log_event qinfo(thd, thd->query);
|
||||
if (mysql_bin_log.write(&qinfo) &&
|
||||
!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 */
|
||||
|
||||
VOID(ha_autocommit_or_rollback(thd,error > 0));
|
||||
}
|
||||
|
||||
|
|
|
@ -2423,7 +2423,6 @@ mysql_init_query(THD *thd)
|
|||
thd->fatal_error=0; // Safety
|
||||
thd->last_insert_id_used=thd->query_start_used=thd->insert_id_used=0;
|
||||
thd->sent_row_count=thd->examined_row_count=0;
|
||||
thd->lex.sql_command=SQLCOM_SELECT;
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
@ -2860,13 +2859,17 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias,
|
|||
if (!alias) /* Alias is case sensitive */
|
||||
if (!(alias_str=thd->memdup(alias_str,table->table.length+1)))
|
||||
DBUG_RETURN(0);
|
||||
if (lower_case_table_names)
|
||||
casedn_str(table->table.str);
|
||||
|
||||
if (!(ptr = (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST))))
|
||||
DBUG_RETURN(0); /* purecov: inspected */
|
||||
ptr->db= table->db.str ? table->db.str : (thd->db ? thd->db : (char*) "");
|
||||
ptr->real_name=table->table.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->updating=updating;
|
||||
if (use_index)
|
||||
|
@ -2879,7 +2882,8 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias,
|
|||
/* check that used name is unique */
|
||||
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)
|
||||
{
|
||||
if (!strcmp(alias_str,tables->name) && !strcmp(ptr->db, tables->db))
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
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;
|
||||
List<Item> item_list;
|
||||
TABLE *table;
|
||||
|
@ -38,7 +38,10 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
|
|||
DBUG_ENTER("mysql_union");
|
||||
|
||||
/* 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;
|
||||
cursor;
|
||||
|
@ -46,19 +49,27 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
|
|||
cursor->table= ((TABLE_LIST*) cursor->table)->table;
|
||||
}
|
||||
|
||||
/* last_sel now points at the last select where the ORDER BY is stored */
|
||||
if (sl)
|
||||
{
|
||||
lex_sl=*sl;
|
||||
sl=(SELECT_LEX *)NULL;
|
||||
if (last_sl) last_sl->next=sl;
|
||||
/*
|
||||
The found SL is an extra SELECT_LEX argument that contains
|
||||
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
|
||||
lex_sl.linkage=UNSPECIFIED_TYPE;
|
||||
|
||||
/* Find last select part as it's here ORDER BY and GROUP BY is stored */
|
||||
for (last_sl= &lex->select_lex;
|
||||
last_sl->next;
|
||||
last_sl=last_sl->next) ;
|
||||
{
|
||||
lex_sl=0;
|
||||
order=0;
|
||||
}
|
||||
|
||||
if (lex->select_lex.options & SELECT_DESCRIBE)
|
||||
{
|
||||
|
@ -68,7 +79,8 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
|
|||
res=mysql_select(thd, (TABLE_LIST*) sl->table_list.first,
|
||||
sl->item_list,
|
||||
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,
|
||||
sl->having,
|
||||
(ORDER*) NULL,
|
||||
|
@ -79,8 +91,6 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
|
|||
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;
|
||||
List_iterator<Item> it(lex->select_lex.item_list);
|
||||
|
@ -162,11 +172,11 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
|
|||
}
|
||||
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->select_limit=lex_sl.select_limit+lex_sl.offset_limit;
|
||||
if (thd->select_limit < lex_sl.select_limit)
|
||||
thd->offset_limit=lex_sl->offset_limit;
|
||||
thd->select_limit=lex_sl->select_limit+lex_sl->offset_limit;
|
||||
if (thd->select_limit < lex_sl->select_limit)
|
||||
thd->select_limit= HA_POS_ERROR; // no limit
|
||||
if (thd->select_limit == HA_POS_ERROR)
|
||||
thd->options&= ~OPTION_FOUND_ROWS;
|
||||
|
|
|
@ -1348,9 +1348,13 @@ table_to_table:
|
|||
|
||||
|
||||
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:
|
||||
{
|
||||
|
@ -1643,10 +1647,14 @@ simple_expr:
|
|||
{ $$= new Item_func_decode($3,$5.str); }
|
||||
| ENCODE_SYM '(' expr ',' TEXT_STRING ')'
|
||||
{ $$= new Item_func_encode($3,$5.str); }
|
||||
| DES_DECRYPT '(' expr ',' expr ')'
|
||||
{ $$= new Item_func_des_decrypt($3,$5); }
|
||||
| DES_ENCRYPT '(' expr ',' expr ')'
|
||||
{ $$= new Item_func_des_encrypt($3,$5); }
|
||||
| DES_DECRYPT '(' expr ')'
|
||||
{ $$= new Item_func_des_decrypt($3); }
|
||||
| DES_DECRYPT '(' expr ',' expr ')'
|
||||
{ $$= 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 ')'
|
||||
{ $$= new Item_func_export_set($3, $5, $7); }
|
||||
| EXPORT_SET '(' expr ',' expr ',' expr ',' expr ')'
|
||||
|
@ -3573,12 +3581,12 @@ union_list:
|
|||
net_printf(&lex->thd->net, ER_WRONG_USAGE,"UNION","INTO");
|
||||
YYABORT;
|
||||
}
|
||||
if (lex->select->linkage==NOT_A_SELECT)
|
||||
if (lex->select->linkage == NOT_A_SELECT)
|
||||
YYABORT;
|
||||
mysql_new_select(lex);
|
||||
lex->select->linkage=UNION_TYPE;
|
||||
}
|
||||
select
|
||||
select_init
|
||||
|
||||
union_opt:
|
||||
union {}
|
||||
|
|
Loading…
Reference in a new issue