Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
MariaDB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
b883a9c0
Commit
b883a9c0
authored
Mar 19, 2003
by
monty@narttu.mysql.fi
Browse files
Options
Browse Files
Download
Plain Diff
Merge with 4.0.12
parents
48a9c123
58472943
Changes
45
Hide whitespace changes
Inline
Side-by-side
Showing
45 changed files
with
624 additions
and
291 deletions
+624
-291
Docs/internals.texi
Docs/internals.texi
+11
-8
client/mysql.cc
client/mysql.cc
+2
-1
client/password.c
client/password.c
+0
-191
include/Makefile.am
include/Makefile.am
+1
-1
include/my_dbug.h
include/my_dbug.h
+0
-0
include/my_global.h
include/my_global.h
+1
-1
include/mysql_com.h
include/mysql_com.h
+1
-1
innobase/row/row0mysql.c
innobase/row/row0mysql.c
+1
-1
libmysql/Makefile.am
libmysql/Makefile.am
+3
-5
libmysql/get_password.c
libmysql/get_password.c
+0
-1
libmysql/password.c
libmysql/password.c
+0
-0
libmysqld/Makefile.am
libmysqld/Makefile.am
+2
-2
libmysqld/lib_vio.c
libmysqld/lib_vio.c
+0
-1
mysql-test/r/create.result
mysql-test/r/create.result
+23
-0
mysql-test/r/heap.result
mysql-test/r/heap.result
+1
-1
mysql-test/r/innodb.result
mysql-test/r/innodb.result
+111
-1
mysql-test/r/multi_update.result
mysql-test/r/multi_update.result
+64
-0
mysql-test/r/rpl_relayspace.result
mysql-test/r/rpl_relayspace.result
+13
-0
mysql-test/t/create.test
mysql-test/t/create.test
+15
-0
mysql-test/t/heap.test
mysql-test/t/heap.test
+1
-1
mysql-test/t/innodb.test
mysql-test/t/innodb.test
+72
-1
mysql-test/t/multi_update.test
mysql-test/t/multi_update.test
+28
-0
mysql-test/t/rpl_relayspace-slave.opt
mysql-test/t/rpl_relayspace-slave.opt
+1
-0
mysql-test/t/rpl_relayspace.test
mysql-test/t/rpl_relayspace.test
+33
-0
sql/ha_innodb.h
sql/ha_innodb.h
+1
-2
sql/ha_myisam.cc
sql/ha_myisam.cc
+30
-0
sql/handler.cc
sql/handler.cc
+8
-1
sql/handler.h
sql/handler.h
+0
-1
sql/item_func.cc
sql/item_func.cc
+1
-1
sql/key.cc
sql/key.cc
+8
-0
sql/lex.h
sql/lex.h
+1
-0
sql/log.cc
sql/log.cc
+2
-0
sql/mysqld.cc
sql/mysqld.cc
+1
-1
sql/password.c
sql/password.c
+6
-6
sql/slave.cc
sql/slave.cc
+51
-9
sql/slave.h
sql/slave.h
+7
-0
sql/sql_class.cc
sql/sql_class.cc
+1
-1
sql/sql_crypt.cc
sql/sql_crypt.cc
+3
-3
sql/sql_parse.cc
sql/sql_parse.cc
+3
-0
sql/sql_repl.cc
sql/sql_repl.cc
+4
-4
sql/sql_show.cc
sql/sql_show.cc
+2
-2
sql/sql_update.cc
sql/sql_update.cc
+105
-42
sql/sql_yacc.yy
sql/sql_yacc.yy
+3
-0
sql/table.cc
sql/table.cc
+1
-1
strings/strto.c
strings/strto.c
+2
-0
No files found.
Docs/internals.texi
View file @
b883a9c0
...
...
@@ -2798,11 +2798,11 @@ Storage: same as TINYINT.
@strong
{
DATE
}
@itemize @bullet
@item
Storage:
fixed-length series of binary integers, always three bytes
long.
Storage:
3 byte integer, low byte first.
Packed as: 'day + month*32 + year*16*32'
@item
Example: a DATE column containing '
0001-01-01
' looks like:@*
@code
{
hexadecimal 2
1 02 00
}
Example: a DATE column containing '
1962-01-02
' looks like:@*
@code
{
hexadecimal 2
2 54 0F
}
@end itemize
@strong
{
DATETIME
}
...
...
@@ -2821,16 +2821,19 @@ Example: a DATETIME column for '0001-01-01 01:01:01' looks like:@*
@strong
{
TIME
}
@itemize @bullet
@item
Storage: a value offset from 8385959, always three bytes long.
Storage: 3 bytes, low byte first.
This is stored as seconds: days*24*3600+hours*3600+minutes*60+seconds
@item
Example: a TIME column containing '
01:01:01'
looks like:@*
@code
{
hexadecimal
75 27 00
}
Example: a TIME column containing '
1 02:03:04' (1 day 2 hour 3 minutes and 4 seconds)
looks like:@*
@code
{
hexadecimal
58 6E 01
}
@end itemize
@strong
{
TIMESTAMP
}
@itemize @bullet
@item
Storage: four bytes long (NOTE TO SELF: not figured out)
Storage: 4 bytes, low byte first.
Stored as unix @code
{
time()
}
, which is seconds since the Epoch
(00:00:00 UTC, January 1, 1970).
@item
Example: a TIMESTAMP column containing '2003-01-01 01:01:01' looks like:@*
@code
{
hexadecimal 4D AE 12 23
}
...
...
client/mysql.cc
View file @
b883a9c0
...
...
@@ -40,7 +40,7 @@
#include <signal.h>
#include <violite.h>
const
char
*
VER
=
"13.
4
"
;
const
char
*
VER
=
"13.
5
"
;
/* Don't try to make a nice table if the data is too big */
#define MAX_COLUMN_LENGTH 1024
...
...
@@ -799,6 +799,7 @@ static int get_options(int argc, char **argv)
}
if
(
argc
==
1
)
{
skip_updates
=
0
;
my_free
(
current_db
,
MYF
(
MY_ALLOW_ZERO_PTR
));
current_db
=
my_strdup
(
*
argv
,
MYF
(
MY_WME
));
}
...
...
client/password.c
deleted
100644 → 0
View file @
48a9c123
/* Copyright (C) 2000 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* password checking routines */
/*****************************************************************************
The main idea is that no password are sent between client & server on
connection and that no password are saved in mysql in a decodable form.
On connection a random string is generated and sent to the client.
The client generates a new string with a random generator inited with
the hash values from the password and the sent string.
This 'check' string is sent to the server where it is compared with
a string generated from the stored hash_value of the password and the
random string.
The password is saved (in user.password) by using the PASSWORD() function in
mysql.
Example:
update user set password=PASSWORD("hello") where user="test"
This saves a hashed number as a string in the password field.
*****************************************************************************/
#include <my_global.h>
#include <my_sys.h>
#include <m_string.h>
#include "mysql.h"
void
randominit
(
struct
rand_struct
*
rand_st
,
ulong
seed1
,
ulong
seed2
)
{
/* For mysql 3.21.# */
#ifdef HAVE_purify
bzero
((
char
*
)
rand_st
,
sizeof
(
*
rand_st
));
/* Avoid UMC varnings */
#endif
rand_st
->
max_value
=
0x3FFFFFFFL
;
rand_st
->
max_value_dbl
=
(
double
)
rand_st
->
max_value
;
rand_st
->
seed1
=
seed1
%
rand_st
->
max_value
;
rand_st
->
seed2
=
seed2
%
rand_st
->
max_value
;
}
static
void
old_randominit
(
struct
rand_struct
*
rand_st
,
ulong
seed1
)
{
/* For mysql 3.20.# */
rand_st
->
max_value
=
0x01FFFFFFL
;
rand_st
->
max_value_dbl
=
(
double
)
rand_st
->
max_value
;
seed1
%=
rand_st
->
max_value
;
rand_st
->
seed1
=
seed1
;
rand_st
->
seed2
=
seed1
/
2
;
}
double
rnd
(
struct
rand_struct
*
rand_st
)
{
rand_st
->
seed1
=
(
rand_st
->
seed1
*
3
+
rand_st
->
seed2
)
%
rand_st
->
max_value
;
rand_st
->
seed2
=
(
rand_st
->
seed1
+
rand_st
->
seed2
+
33
)
%
rand_st
->
max_value
;
return
(((
double
)
rand_st
->
seed1
)
/
rand_st
->
max_value_dbl
);
}
void
hash_password
(
ulong
*
result
,
const
char
*
password
)
{
register
ulong
nr
=
1345345333L
,
add
=
7
,
nr2
=
0x12345671L
;
ulong
tmp
;
for
(;
*
password
;
password
++
)
{
if
(
*
password
==
' '
||
*
password
==
'\t'
)
continue
;
/* skipp space in password */
tmp
=
(
ulong
)
(
uchar
)
*
password
;
nr
^=
(((
nr
&
63
)
+
add
)
*
tmp
)
+
(
nr
<<
8
);
nr2
+=
(
nr2
<<
8
)
^
nr
;
add
+=
tmp
;
}
result
[
0
]
=
nr
&
(((
ulong
)
1L
<<
31
)
-
1L
);
/* Don't use sign bit (str2int) */
;
result
[
1
]
=
nr2
&
(((
ulong
)
1L
<<
31
)
-
1L
);
return
;
}
void
make_scrambled_password
(
char
*
to
,
const
char
*
password
)
{
ulong
hash_res
[
2
];
hash_password
(
hash_res
,
password
);
sprintf
(
to
,
"%08lx%08lx"
,
hash_res
[
0
],
hash_res
[
1
]);
}
static
inline
uint
char_val
(
char
X
)
{
return
(
uint
)
(
X
>=
'0'
&&
X
<=
'9'
?
X
-
'0'
:
X
>=
'A'
&&
X
<=
'Z'
?
X
-
'A'
+
10
:
X
-
'a'
+
10
);
}
/*
** This code assumes that len(password) is divideable with 8 and that
** res is big enough (2 in mysql)
*/
void
get_salt_from_password
(
ulong
*
res
,
const
char
*
password
)
{
res
[
0
]
=
res
[
1
]
=
0
;
if
(
password
)
{
while
(
*
password
)
{
ulong
val
=
0
;
uint
i
;
for
(
i
=
0
;
i
<
8
;
i
++
)
val
=
(
val
<<
4
)
+
char_val
(
*
password
++
);
*
res
++=
val
;
}
}
return
;
}
void
make_password_from_salt
(
char
*
to
,
ulong
*
hash_res
)
{
sprintf
(
to
,
"%08lx%08lx"
,
hash_res
[
0
],
hash_res
[
1
]);
}
/*
* Genererate a new message based on message and password
* The same thing is done in client and server and the results are checked.
*/
char
*
scramble
(
char
*
to
,
const
char
*
message
,
const
char
*
password
,
my_bool
old_ver
)
{
struct
rand_struct
rand_st
;
ulong
hash_pass
[
2
],
hash_message
[
2
];
if
(
password
&&
password
[
0
])
{
char
*
to_start
=
to
;
hash_password
(
hash_pass
,
password
);
hash_password
(
hash_message
,
message
);
if
(
old_ver
)
old_randominit
(
&
rand_st
,
hash_pass
[
0
]
^
hash_message
[
0
]);
else
randominit
(
&
rand_st
,
hash_pass
[
0
]
^
hash_message
[
0
],
hash_pass
[
1
]
^
hash_message
[
1
]);
while
(
*
message
++
)
*
to
++=
(
char
)
(
floor
(
rnd
(
&
rand_st
)
*
31
)
+
64
);
if
(
!
old_ver
)
{
/* Make it harder to break */
char
extra
=
(
char
)
(
floor
(
rnd
(
&
rand_st
)
*
31
));
while
(
to_start
!=
to
)
*
(
to_start
++
)
^=
extra
;
}
}
*
to
=
0
;
return
to
;
}
my_bool
check_scramble
(
const
char
*
scrambled
,
const
char
*
message
,
ulong
*
hash_pass
,
my_bool
old_ver
)
{
struct
rand_struct
rand_st
;
ulong
hash_message
[
2
];
char
buff
[
16
],
*
to
,
extra
;
/* Big enough for check */
const
char
*
pos
;
hash_password
(
hash_message
,
message
);
if
(
old_ver
)
old_randominit
(
&
rand_st
,
hash_pass
[
0
]
^
hash_message
[
0
]);
else
randominit
(
&
rand_st
,
hash_pass
[
0
]
^
hash_message
[
0
],
hash_pass
[
1
]
^
hash_message
[
1
]);
to
=
buff
;
for
(
pos
=
scrambled
;
*
pos
;
pos
++
)
*
to
++=
(
char
)
(
floor
(
rnd
(
&
rand_st
)
*
31
)
+
64
);
if
(
old_ver
)
extra
=
0
;
else
extra
=
(
char
)
(
floor
(
rnd
(
&
rand_st
)
*
31
));
to
=
buff
;
while
(
*
scrambled
)
{
if
(
*
scrambled
++
!=
(
char
)
(
*
to
++
^
extra
))
return
1
;
/* Wrong password */
}
return
0
;
}
include/Makefile.am
View file @
b883a9c0
...
...
@@ -16,7 +16,7 @@
# MA 02111-1307, USA
BUILT_SOURCES
=
mysql_version.h m_ctype.h my_config.h
pkginclude_HEADERS
=
dbug.h m_string.h my_sys.h my_list.h my_xml.h
\
pkginclude_HEADERS
=
my_
dbug.h m_string.h my_sys.h my_list.h my_xml.h
\
mysql.h mysql_com.h mysqld_error.h mysql_embed.h
\
my_semaphore.h my_pthread.h my_no_pthread.h raid.h
\
errmsg.h my_global.h my_net.h my_alloc.h
\
...
...
include/dbug.h
→
include/
my_
dbug.h
View file @
b883a9c0
File moved
include/my_global.h
View file @
b883a9c0
...
...
@@ -417,7 +417,7 @@ typedef unsigned short ushort;
#define DBUG_OFF
#endif
#include <dbug.h>
#include <
my_
dbug.h>
#define MIN_ARRAY_SIZE 0
/* Zero or One. Gcc allows zero*/
#define ASCII_BITS_USED 8
/* Bit char used */
...
...
include/mysql_com.h
View file @
b883a9c0
...
...
@@ -298,7 +298,7 @@ extern unsigned long net_buffer_length;
void
randominit
(
struct
rand_struct
*
,
unsigned
long
seed1
,
unsigned
long
seed2
);
double
rnd
(
struct
rand_struct
*
);
double
my_
rnd
(
struct
rand_struct
*
);
void
make_scrambled_password
(
char
*
to
,
const
char
*
password
,
my_bool
force_old_scramble
,
struct
rand_struct
*
rand_st
);
int
get_password_length
(
my_bool
force_old_scramble
);
...
...
innobase/row/row0mysql.c
View file @
b883a9c0
...
...
@@ -6,7 +6,7 @@ Contains also create table and other data dictionary operations.
Created 9/17/2000 Heikki Tuuri
*******************************************************/
#include "row0mysql.h"
#ifdef UNIV_NONINL
...
...
libmysql/Makefile.am
View file @
b883a9c0
...
...
@@ -48,10 +48,6 @@ link_sources:
rm
-f
$(srcdir)
/
$$
f
;
\
@LN_CP_F@
$(srcdir)
/../strings/
$$
f
$(srcdir)
/
$$
f
;
\
done
;
\
for
f
in
$$
qs
;
do
\
rm
-f
$(srcdir)
/
$$
f
;
\
@LN_CP_F@
$(srcdir)
/../sql/
$$
f
$(srcdir)
/
$$
f
;
\
done
;
\
for
f
in
$$
ds
;
do
\
rm
-f
$(srcdir)
/
$$
f
;
\
@LN_CP_F@
$(srcdir)
/../dbug/
$$
f
$(srcdir)
/
$$
f
;
\
...
...
@@ -61,7 +57,9 @@ link_sources:
@LN_CP_F@
$(srcdir)
/../mysys/
$$
f
$(srcdir)
/
$$
f
;
\
done
;
\
rm
-f
$(srcdir)
/net.c
;
\
@LN_CP_F@
$(srcdir)
/../sql/net_serv.cc
$(srcdir)
/net.c
@LN_CP_F@
$(srcdir)
/../sql/net_serv.cc
$(srcdir)
/net.c
;
\
rm
-f
$(srcdir)
/password.c
;
\
@LN_CP_F@
$(srcdir)
/../sql/password.c
$(srcdir)
/password.c
# This part requires GNUmake
#
...
...
libmysql/get_password.c
View file @
b883a9c0
...
...
@@ -23,7 +23,6 @@
#include "mysql.h"
#include <m_string.h>
#include <m_ctype.h>
#include <dbug.h>
#if defined(HAVE_BROKEN_GETPASS) && !defined(HAVE_GETPASSPHRASE)
#undef HAVE_GETPASS
...
...
libmysql/password.c
deleted
100755 → 0
View file @
48a9c123
libmysqld/Makefile.am
View file @
b883a9c0
...
...
@@ -32,14 +32,14 @@ noinst_LIBRARIES = libmysqld_int.a
pkglib_LIBRARIES
=
libmysqld.a
SUBDIRS
=
.
examples
libmysqld_sources
=
libmysqld.c lib_sql.cc
libmysqlsources
=
errmsg.c get_password.c
password.c
libmysqlsources
=
errmsg.c get_password.c
noinst_HEADERS
=
embedded_priv.h
sqlsources
=
convert.cc derror.cc field.cc field_conv.cc filesort.cc
\
ha_innodb.cc ha_berkeley.cc ha_heap.cc ha_isam.cc ha_isammrg.cc
\
ha_myisam.cc ha_myisammrg.cc handler.cc sql_handler.cc
\
hostname.cc init.cc
\
hostname.cc init.cc
password.c
\
item.cc item_buff.cc item_cmpfunc.cc item_create.cc
\
item_func.cc item_strfunc.cc item_sum.cc item_timefunc.cc
\
item_uniq.cc item_subselect.cc item_row.cc
\
...
...
libmysqld/lib_vio.c
View file @
b883a9c0
...
...
@@ -33,7 +33,6 @@
#include <violite.h>
#include <my_net.h>
#include <m_string.h>
#include <dbug.h>
#include <assert.h>
#ifndef __WIN__
...
...
mysql-test/r/create.result
View file @
b883a9c0
...
...
@@ -253,3 +253,26 @@ Incorrect table name 'a/a'
drop table t1, t2, t3;
drop table t3;
drop database test_$1;
SET SESSION table_type="heap";
SELECT @@table_type;
@@table_type
HEAP
CREATE TABLE t1 (a int not null);
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL default '0'
) TYPE=HEAP
drop table t1;
SET SESSION table_type="gemini";
SELECT @@table_type;
@@table_type
GEMINI
CREATE TABLE t1 (a int not null);
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL default '0'
) TYPE=MyISAM
SET SESSION table_type=default;
drop table t1;
mysql-test/r/heap.result
View file @
b883a9c0
...
...
@@ -23,7 +23,7 @@ a b
4 6
alter table t1 add c int not null, add key (c,a);
drop table t1;
create table t1 (a int not null,b int not null, primary key (a)) type=
heap
comment="testing heaps";
create table t1 (a int not null,b int not null, primary key (a)) type=
memory
comment="testing heaps";
insert into t1 values(1,1),(2,2),(3,3),(4,4);
delete from t1 where a > 0;
select * from t1;
...
...
mysql-test/r/innodb.result
View file @
b883a9c0
drop table if exists t1,t2;
drop table if exists t1,t2
,t3
;
create table t1 (id int unsigned not null auto_increment, code tinyint unsigned not null, name char(20) not null, primary key (id), key (code), unique (name)) type=innodb;
insert into t1 (code, name) values (1, 'Tim'), (1, 'Monty'), (2, 'David'), (2, 'Erik'), (3, 'Sasha'), (3, 'Jeremy'), (4, 'Matt');
select id, code, name from t1 order by id;
...
...
@@ -1093,3 +1093,113 @@ SELECT * from t1;
id
3
DROP TABLE t1,t2;
set autocommit=0;
CREATE TABLE t1 (id CHAR(15) NOT NULL, value CHAR(40) NOT NULL, PRIMARY KEY(id)) TYPE=InnoDB;
CREATE TABLE t2 (id CHAR(15) NOT NULL, value CHAR(40) NOT NULL, PRIMARY KEY(id)) TYPE=InnoDB;
CREATE TABLE t3 (id1 CHAR(15) NOT NULL, id2 CHAR(15) NOT NULL, PRIMARY KEY(id1, id2)) TYPE=InnoDB;
INSERT INTO t3 VALUES("my-test-1", "my-test-2");
COMMIT;
INSERT INTO t1 VALUES("this-key", "will disappear");
INSERT INTO t2 VALUES("this-key", "will also disappear");
DELETE FROM t3 WHERE id1="my-test-1";
SELECT * FROM t1;
id value
this-key will disappear
SELECT * FROM t2;
id value
this-key will also disappear
SELECT * FROM t3;
id1 id2
ROLLBACK;
SELECT * FROM t1;
id value
SELECT * FROM t2;
id value
SELECT * FROM t3;
id1 id2
my-test-1 my-test-2
SELECT * FROM t3 WHERE id1="my-test-1" LOCK IN SHARE MODE;
id1 id2
my-test-1 my-test-2
COMMIT;
set autocommit=1;
DROP TABLE t1,t2,t3;
CREATE TABLE t1 (a int not null primary key, b int not null, unique (b)) type=innodb;
INSERT INTO t1 values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
UPDATE t1 set a=a+100 where b between 2 and 3 and a < 1000;
SELECT * from t1;
a b
1 1
102 2
103 3
4 4
5 5
6 6
7 7
8 8
9 9
drop table t1;
CREATE TABLE t1 (a int not null primary key, b int not null, key (b)) type=innodb;
CREATE TABLE t2 (a int not null primary key, b int not null, key (b)) type=innodb;
INSERT INTO t1 values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
INSERT INTO t2 values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
update t1,t2 set t1.a=t1.a+100;
select * from t1;
a b
101 1
102 2
103 3
104 4
105 5
106 6
107 7
108 8
109 9
update t1,t2 set t1.a=t1.a+100 where t1.a=101;
select * from t1;
a b
201 1
102 2
103 3
104 4
105 5
106 6
107 7
108 8
109 9
update t1,t2 set t1.b=t1.b+10 where t1.b=2;
select * from t1;
a b
201 1
103 3
104 4
105 5
106 6
107 7
108 8
109 9
102 12
update t1,t2 set t1.b=t1.b+2,t2.b=t1.b where t1.b between 3 and 5;
select * from t1;
a b
201 1
103 5
104 6
106 6
105 7
107 7
108 8
109 9
102 12
select * from t2;
a b
1 5
2 5
3 5
4 5
5 5
6 5
7 5
8 5
9 5
drop table t1,t2;
mysql-test/r/multi_update.result
View file @
b883a9c0
...
...
@@ -260,3 +260,67 @@ INSERT INTO t3 VALUES (1,'jedan'),(2,'dva');
update t1,t2 set t1.naziv="aaaa" where t1.broj=t2.broj;
update t1,t2,t3 set t1.naziv="bbbb", t2.naziv="aaaa" where t1.broj=t2.broj and t2.broj=t3.broj;
drop table t1,t2,t3;
CREATE TABLE t1 (a int not null primary key, b int not null, key (b));
CREATE TABLE t2 (a int not null primary key, b int not null, key (b));
INSERT INTO t1 values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
INSERT INTO t2 values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
update t1,t2 set t1.a=t1.a+100;
select * from t1;
a b
101 1
102 2
103 3
104 4
105 5
106 6
107 7
108 8
109 9
update t1,t2 set t1.a=t1.a+100 where t1.a=101;
select * from t1;
a b
201 1
102 2
103 3
104 4
105 5
106 6
107 7
108 8
109 9
update t1,t2 set t1.b=t1.b+10 where t1.b=2;
select * from t1;
a b
201 1
102 12
103 3
104 4
105 5
106 6
107 7
108 8
109 9
update t1,t2 set t1.b=t1.b+2,t2.b=t1.b where t1.b between 3 and 5;
select * from t1;
a b
201 1
102 12
103 5
104 6
105 7
106 6
107 7
108 8
109 9
select * from t2;
a b
1 3
2 3
3 3
4 3
5 3
6 3
7 3
8 3
9 3
drop table t1,t2;
mysql-test/r/rpl_relayspace.result
0 → 100644
View file @
b883a9c0
slave stop;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
slave start;
stop slave;
create table t1 (a int);
reset slave;
start slave;
select master_pos_wait('master-bin.001',5000,45)=-1;
master_pos_wait('master-bin.001',5000,45)=-1
0
mysql-test/t/create.test
View file @
b883a9c0
...
...
@@ -167,3 +167,18 @@ drop table t1, t2, t3;
drop
table
t3
;
drop
database
test_
$
1
;
#
# Test default table type
#
SET
SESSION
table_type
=
"heap"
;
SELECT
@@
table_type
;
CREATE
TABLE
t1
(
a
int
not
null
);
show
create
table
t1
;
drop
table
t1
;
# Test what happens when using a non existing table type
SET
SESSION
table_type
=
"gemini"
;
SELECT
@@
table_type
;
CREATE
TABLE
t1
(
a
int
not
null
);
show
create
table
t1
;
SET
SESSION
table_type
=
default
;
drop
table
t1
;
mysql-test/t/heap.test
View file @
b883a9c0
...
...
@@ -20,7 +20,7 @@ select * from t1;
alter
table
t1
add
c
int
not
null
,
add
key
(
c
,
a
);
drop
table
t1
;
create
table
t1
(
a
int
not
null
,
b
int
not
null
,
primary
key
(
a
))
type
=
heap
comment
=
"testing heaps"
;
create
table
t1
(
a
int
not
null
,
b
int
not
null
,
primary
key
(
a
))
type
=
memory
comment
=
"testing heaps"
;
insert
into
t1
values
(
1
,
1
),(
2
,
2
),(
3
,
3
),(
4
,
4
);
delete
from
t1
where
a
>
0
;
select
*
from
t1
;
...
...
mysql-test/t/innodb.test
View file @
b883a9c0
...
...
@@ -5,7 +5,7 @@
#
--
disable_warnings
drop
table
if
exists
t1
,
t2
;
drop
table
if
exists
t1
,
t2
,
t3
;
--
enable_warnings
create
table
t1
(
id
int
unsigned
not
null
auto_increment
,
code
tinyint
unsigned
not
null
,
name
char
(
20
)
not
null
,
primary
key
(
id
),
key
(
code
),
unique
(
name
))
type
=
innodb
;
...
...
@@ -728,3 +728,74 @@ SELECT * from t1;
UPDATE
t1
,
t2
SET
t1
.
id
=
t1
.
id
+
1
where
t1
.
id
!=
t2
.
id
;
SELECT
*
from
t1
;
DROP
TABLE
t1
,
t2
;
#
# Test of range_optimizer
#
set
autocommit
=
0
;
CREATE
TABLE
t1
(
id
CHAR
(
15
)
NOT
NULL
,
value
CHAR
(
40
)
NOT
NULL
,
PRIMARY
KEY
(
id
))
TYPE
=
InnoDB
;
CREATE
TABLE
t2
(
id
CHAR
(
15
)
NOT
NULL
,
value
CHAR
(
40
)
NOT
NULL
,
PRIMARY
KEY
(
id
))
TYPE
=
InnoDB
;
CREATE
TABLE
t3
(
id1
CHAR
(
15
)
NOT
NULL
,
id2
CHAR
(
15
)
NOT
NULL
,
PRIMARY
KEY
(
id1
,
id2
))
TYPE
=
InnoDB
;
INSERT
INTO
t3
VALUES
(
"my-test-1"
,
"my-test-2"
);
COMMIT
;
INSERT
INTO
t1
VALUES
(
"this-key"
,
"will disappear"
);
INSERT
INTO
t2
VALUES
(
"this-key"
,
"will also disappear"
);
DELETE
FROM
t3
WHERE
id1
=
"my-test-1"
;
SELECT
*
FROM
t1
;
SELECT
*
FROM
t2
;
SELECT
*
FROM
t3
;
ROLLBACK
;
SELECT
*
FROM
t1
;
SELECT
*
FROM
t2
;
SELECT
*
FROM
t3
;
SELECT
*
FROM
t3
WHERE
id1
=
"my-test-1"
LOCK
IN
SHARE
MODE
;
COMMIT
;
set
autocommit
=
1
;
DROP
TABLE
t1
,
t2
,
t3
;
#
# Check update with conflicting key
#
CREATE
TABLE
t1
(
a
int
not
null
primary
key
,
b
int
not
null
,
unique
(
b
))
type
=
innodb
;
INSERT
INTO
t1
values
(
1
,
1
),(
2
,
2
),(
3
,
3
),(
4
,
4
),(
5
,
5
),(
6
,
6
),(
7
,
7
),(
8
,
8
),(
9
,
9
);
# We need the a < 1000 test here to quard against the halloween problems
UPDATE
t1
set
a
=
a
+
100
where
b
between
2
and
3
and
a
<
1000
;
SELECT
*
from
t1
;
drop
table
t1
;
#
# Test multi update with different join methods
#
CREATE
TABLE
t1
(
a
int
not
null
primary
key
,
b
int
not
null
,
key
(
b
))
type
=
innodb
;
CREATE
TABLE
t2
(
a
int
not
null
primary
key
,
b
int
not
null
,
key
(
b
))
type
=
innodb
;
INSERT
INTO
t1
values
(
1
,
1
),(
2
,
2
),(
3
,
3
),(
4
,
4
),(
5
,
5
),(
6
,
6
),(
7
,
7
),(
8
,
8
),(
9
,
9
);
INSERT
INTO
t2
values
(
1
,
1
),(
2
,
2
),(
3
,
3
),(
4
,
4
),(
5
,
5
),(
6
,
6
),(
7
,
7
),(
8
,
8
),(
9
,
9
);
# Full join, without key
update
t1
,
t2
set
t1
.
a
=
t1
.
a
+
100
;
select
*
from
t1
;
# unique key
update
t1
,
t2
set
t1
.
a
=
t1
.
a
+
100
where
t1
.
a
=
101
;
select
*
from
t1
;
# ref key
update
t1
,
t2
set
t1
.
b
=
t1
.
b
+
10
where
t1
.
b
=
2
;
select
*
from
t1
;
# Range key (in t1)
update
t1
,
t2
set
t1
.
b
=
t1
.
b
+
2
,
t2
.
b
=
t1
.
b
where
t1
.
b
between
3
and
5
;
select
*
from
t1
;
select
*
from
t2
;
drop
table
t1
,
t2
;
mysql-test/t/multi_update.test
View file @
b883a9c0
...
...
@@ -232,3 +232,31 @@ INSERT INTO t3 VALUES (1,'jedan'),(2,'dva');
update
t1
,
t2
set
t1
.
naziv
=
"aaaa"
where
t1
.
broj
=
t2
.
broj
;
update
t1
,
t2
,
t3
set
t1
.
naziv
=
"bbbb"
,
t2
.
naziv
=
"aaaa"
where
t1
.
broj
=
t2
.
broj
and
t2
.
broj
=
t3
.
broj
;
drop
table
t1
,
t2
,
t3
;
#
# Test multi update with different join methods
#
CREATE
TABLE
t1
(
a
int
not
null
primary
key
,
b
int
not
null
,
key
(
b
));
CREATE
TABLE
t2
(
a
int
not
null
primary
key
,
b
int
not
null
,
key
(
b
));
INSERT
INTO
t1
values
(
1
,
1
),(
2
,
2
),(
3
,
3
),(
4
,
4
),(
5
,
5
),(
6
,
6
),(
7
,
7
),(
8
,
8
),(
9
,
9
);
INSERT
INTO
t2
values
(
1
,
1
),(
2
,
2
),(
3
,
3
),(
4
,
4
),(
5
,
5
),(
6
,
6
),(
7
,
7
),(
8
,
8
),(
9
,
9
);
# Full join, without key
update
t1
,
t2
set
t1
.
a
=
t1
.
a
+
100
;
select
*
from
t1
;
# unique key
update
t1
,
t2
set
t1
.
a
=
t1
.
a
+
100
where
t1
.
a
=
101
;
select
*
from
t1
;
# ref key
update
t1
,
t2
set
t1
.
b
=
t1
.
b
+
10
where
t1
.
b
=
2
;
select
*
from
t1
;
# Range key (in t1)
update
t1
,
t2
set
t1
.
b
=
t1
.
b
+
2
,
t2
.
b
=
t1
.
b
where
t1
.
b
between
3
and
5
;
select
*
from
t1
;
select
*
from
t2
;
drop
table
t1
,
t2
;
mysql-test/t/rpl_relayspace-slave.opt
0 → 100644
View file @
b883a9c0
-O relay_log_space_limit=1024
\ No newline at end of file
mysql-test/t/rpl_relayspace.test
0 → 100644
View file @
b883a9c0
# The slave is started with relay_log_space_limit=1024 bytes,
# to force the deadlock
source
include
/
master
-
slave
.
inc
;
connection
slave
;
stop
slave
;
connection
master
;
create
table
t1
(
a
int
);
let
$
1
=
200
;
disable_query_log
;
while
(
$
1
)
{
# eval means expand $ expressions
eval
insert
into
t1
values
(
$
1
);
dec
$
1
;
}
# This will generate one 10kB master's binlog
enable_query_log
;
save_master_pos
;
connection
slave
;
reset
slave
;
start
slave
;
# The I/O thread stops filling the relay log when
# it's 1kB. And the SQL thread cannot purge this relay log
# as purge is done only when the SQL thread switches to another
# relay log, which does not exist here.
# So we should have a deadlock.
# if it is not resolved automatically we'll detect
# it with master_pos_wait that waits for farther than 1kB;
# it will timeout after 45 seconds;
# also the slave will probably not cooperate to shutdown
# (as 2 threads are locked)
select
master_pos_wait
(
'master-bin.001'
,
5000
,
45
)
=-
1
;
sql/ha_innodb.h
View file @
b883a9c0
...
...
@@ -82,8 +82,7 @@ class ha_innobase: public handler
HA_PRIMARY_KEY_IN_READ_INDEX
|
HA_DROP_BEFORE_CREATE
|
HA_NO_PREFIX_CHAR_KEYS
|
HA_TABLE_SCAN_ON_INDEX
|
HA_NOT_MULTI_UPDATE
),
HA_TABLE_SCAN_ON_INDEX
),
last_dup_key
((
uint
)
-
1
),
start_of_scan
(
0
)
{
...
...
sql/ha_myisam.cc
View file @
b883a9c0
...
...
@@ -1258,6 +1258,35 @@ longlong ha_myisam::get_auto_increment()
}
/*
Find out how many rows there is in the given range
SYNOPSIS
records_in_range()
inx Index to use
start_key Start of range. Null pointer if from first key
start_key_len Length of start key
start_search_flag Flag if start key should be included or not
end_key End of range. Null pointer if to last key
end_key_len Length of end key
end_search_flag Flag if start key should be included or not
NOTES
start_search_flag can have one of the following values:
HA_READ_KEY_EXACT Include the key in the range
HA_READ_AFTER_KEY Don't include key in range
end_search_flag can have one of the following values:
HA_READ_BEFORE_KEY Don't include key in range
HA_READ_AFTER_KEY Include all 'end_key' values in the range
RETURN
HA_POS_ERROR Something is wrong with the index tree.
0 There is no matching keys in the given range
number > 0 There is approximately 'number' matching rows in
the range.
*/
ha_rows
ha_myisam
::
records_in_range
(
int
inx
,
const
byte
*
start_key
,
uint
start_key_len
,
enum
ha_rkey_function
start_search_flag
,
...
...
@@ -1272,6 +1301,7 @@ ha_rows ha_myisam::records_in_range(int inx,
end_search_flag
);
}
int
ha_myisam
::
ft_read
(
byte
*
buf
)
{
int
error
;
...
...
sql/handler.cc
View file @
b883a9c0
...
...
@@ -121,8 +121,15 @@ handler *get_new_handler(TABLE *table, enum db_type db_type)
#endif
case
DB_TYPE_HEAP
:
return
new
ha_heap
(
table
);
case
DB_TYPE_MYISAM
:
default:
// should never happen
{
enum
db_type
def
=
(
enum
db_type
)
current_thd
->
variables
.
table_type
;
/* Try first with 'default table type' */
if
(
db_type
!=
def
)
return
get_new_handler
(
table
,
def
);
}
/* Fall back to MyISAM */
case
DB_TYPE_MYISAM
:
return
new
ha_myisam
(
table
);
case
DB_TYPE_MRG_MYISAM
:
return
new
ha_myisammrg
(
table
);
...
...
sql/handler.h
View file @
b883a9c0
...
...
@@ -67,7 +67,6 @@
#define HA_CAN_FULLTEXT (HA_NO_PREFIX_CHAR_KEYS*2)
#define HA_CAN_SQL_HANDLER (HA_CAN_FULLTEXT*2)
#define HA_NO_AUTO_INCREMENT (HA_CAN_SQL_HANDLER*2)
#define HA_NOT_MULTI_UPDATE (HA_NO_AUTO_INCREMENT*2)
/*
Next record gives next record according last record read (even
...
...
sql/item_func.cc
View file @
b883a9c0
...
...
@@ -851,7 +851,7 @@ void Item_func_rand::fix_length_and_dec()
double
Item_func_rand
::
val
()
{
return
rnd
(
rand
);
return
my_
rnd
(
rand
);
}
longlong
Item_func_sign
::
val_int
()
...
...
sql/key.cc
View file @
b883a9c0
...
...
@@ -271,5 +271,13 @@ bool check_if_key_used(TABLE *table, uint idx, List<Item> &fields)
return
1
;
}
}
/*
If table handler has primary key as part of the index, check that primary
key is not updated
*/
if
(
idx
!=
table
->
primary_key
&&
table
->
primary_key
<
MAX_KEY
&&
(
table
->
file
->
table_flags
()
&
HA_PRIMARY_KEY_IN_READ_INDEX
))
return
check_if_key_used
(
table
,
table
->
primary_key
,
fields
);
return
0
;
}
sql/lex.h
View file @
b883a9c0
...
...
@@ -257,6 +257,7 @@ static SYMBOL symbols[] = {
{
"MEDIUMINT"
,
SYM
(
MEDIUMINT
),
0
,
0
},
{
"MERGE"
,
SYM
(
MERGE_SYM
),
0
,
0
},
{
"MEDIUM"
,
SYM
(
MEDIUM_SYM
),
0
,
0
},
{
"MEMORY"
,
SYM
(
MEMORY_SYM
),
0
,
0
},
{
"MIDDLEINT"
,
SYM
(
MEDIUMINT
),
0
,
0
},
/* For powerbuilder */
{
"MIN_ROWS"
,
SYM
(
MIN_ROWS
),
0
,
0
},
{
"MINUTE"
,
SYM
(
MINUTE_SYM
),
0
,
0
},
...
...
sql/log.cc
View file @
b883a9c0
...
...
@@ -654,6 +654,8 @@ int MYSQL_LOG::purge_first_log(struct st_relay_log_info* rli)
*/
pthread_mutex_lock
(
&
rli
->
log_space_lock
);
rli
->
log_space_total
-=
rli
->
relay_log_pos
;
//tell the I/O thread to take the relay_log_space_limit into account
rli
->
ignore_log_space_limit
=
0
;
pthread_mutex_unlock
(
&
rli
->
log_space_lock
);
pthread_cond_broadcast
(
&
rli
->
log_space_cond
);
...
...
sql/mysqld.cc
View file @
b883a9c0
...
...
@@ -2761,7 +2761,7 @@ static void create_new_thread(THD *thd)
max_used_connections
=
thread_count
-
delayed_insert_threads
;
thd
->
thread_id
=
thread_id
++
;
for
(
uint
i
=
0
;
i
<
8
;
i
++
)
// Generate password teststring
thd
->
scramble
[
i
]
=
(
char
)
(
rnd
(
&
sql_rand
)
*
94
+
33
);
thd
->
scramble
[
i
]
=
(
char
)
(
my_
rnd
(
&
sql_rand
)
*
94
+
33
);
thd
->
scramble
[
8
]
=
0
;
// Back it up as old clients may need it
memcpy
(
thd
->
old_scramble
,
thd
->
scramble
,
9
);
...
...
sql/password.c
View file @
b883a9c0
...
...
@@ -125,7 +125,7 @@ static void old_randominit(struct rand_struct *rand_st,ulong seed1)
Generated pseudo random number
*/
double
rnd
(
struct
rand_struct
*
rand_st
)
double
my_
rnd
(
struct
rand_struct
*
rand_st
)
{
rand_st
->
seed1
=
(
rand_st
->
seed1
*
3
+
rand_st
->
seed2
)
%
rand_st
->
max_value
;
rand_st
->
seed2
=
(
rand_st
->
seed1
+
rand_st
->
seed2
+
33
)
%
rand_st
->
max_value
;
...
...
@@ -435,7 +435,7 @@ char get_password_version(const char *password)
inline
u
int
char_val
(
char
X
)
static
inline
unsigned
int
char_val
(
char
X
)
{
return
(
uint
)
(
X
>=
'0'
&&
X
<=
'9'
?
X
-
'0'
:
X
>=
'A'
&&
X
<=
'Z'
?
X
-
'A'
+
10
:
...
...
@@ -652,10 +652,10 @@ char *scramble(char *to,const char *message,const char *password,
randominit
(
&
rand_st
,
hash_pass
[
0
]
^
hash_message
[
0
],
hash_pass
[
1
]
^
hash_message
[
1
]);
while
(
*
msg
++
)
*
to
++=
(
char
)
(
floor
(
rnd
(
&
rand_st
)
*
31
)
+
64
);
*
to
++=
(
char
)
(
floor
(
my_
rnd
(
&
rand_st
)
*
31
)
+
64
);
if
(
!
old_ver
)
{
/* Make it harder to break */
char
extra
=
(
char
)
(
floor
(
rnd
(
&
rand_st
)
*
31
));
char
extra
=
(
char
)
(
floor
(
my_
rnd
(
&
rand_st
)
*
31
));
while
(
to_start
!=
to
)
*
(
to_start
++
)
^=
extra
;
}
...
...
@@ -711,11 +711,11 @@ my_bool check_scramble(const char *scrambled, const char *message,
hash_pass
[
1
]
^
hash_message
[
1
]);
to
=
buff
;
for
(
pos
=
scrambled
;
*
pos
;
pos
++
)
*
to
++=
(
char
)
(
floor
(
rnd
(
&
rand_st
)
*
31
)
+
64
);
*
to
++=
(
char
)
(
floor
(
my_
rnd
(
&
rand_st
)
*
31
)
+
64
);
if
(
old_ver
)
extra
=
0
;
else
extra
=
(
char
)
(
floor
(
rnd
(
&
rand_st
)
*
31
));
extra
=
(
char
)
(
floor
(
my_
rnd
(
&
rand_st
)
*
31
));
to
=
buff
;
while
(
*
scrambled
)
{
...
...
sql/slave.cc
View file @
b883a9c0
...
...
@@ -263,7 +263,7 @@ int init_relay_log_pos(RELAY_LOG_INFO* rli,const char* log,
if
(
log
)
// If not first log
{
if
(
strcmp
(
log
,
rli
->
linfo
.
log_file_name
))
rli
->
skip_log_purge
=
1
;
// Different name; Don't purge
rli
->
skip_log_purge
=
1
;
// Different name; Don't purge
if
(
rli
->
relay_log
.
find_log_pos
(
&
rli
->
linfo
,
log
,
1
))
{
*
errmsg
=
"Could not find target log during relay log initialization"
;
...
...
@@ -298,6 +298,12 @@ int init_relay_log_pos(RELAY_LOG_INFO* rli,const char* log,
my_b_seek
(
rli
->
cur_log
,(
off_t
)
pos
);
err:
/*
If we don't purge, we can't honour relay_log_space_limit ;
silently discard it
*/
if
(
rli
->
skip_log_purge
)
rli
->
log_space_limit
=
0
;
pthread_cond_broadcast
(
&
rli
->
data_cond
);
if
(
need_data_lock
)
pthread_mutex_unlock
(
&
rli
->
data_lock
);
...
...
@@ -1386,7 +1392,8 @@ static bool wait_for_relay_log_space(RELAY_LOG_INFO* rli)
thd
->
proc_info
=
"Waiting for relay log space to free"
;
while
(
rli
->
log_space_limit
<
rli
->
log_space_total
&&
!
(
slave_killed
=
io_slave_killed
(
thd
,
mi
)))
!
(
slave_killed
=
io_slave_killed
(
thd
,
mi
))
&&
!
rli
->
ignore_log_space_limit
)
{
pthread_cond_wait
(
&
rli
->
log_space_cond
,
&
rli
->
log_space_lock
);
}
...
...
@@ -1667,7 +1674,7 @@ bool flush_master_info(MASTER_INFO* mi)
st_relay_log_info
::
st_relay_log_info
()
:
info_fd
(
-
1
),
cur_log_fd
(
-
1
),
master_log_pos
(
0
),
save_temporary_tables
(
0
),
cur_log_old_open_count
(
0
),
log_space_total
(
0
),
cur_log_old_open_count
(
0
),
log_space_total
(
0
),
ignore_log_space_limit
(
0
),
slave_skip_counter
(
0
),
abort_pos_wait
(
0
),
slave_run_id
(
0
),
sql_thd
(
0
),
last_slave_errno
(
0
),
inited
(
0
),
abort_slave
(
0
),
slave_running
(
0
),
skip_log_purge
(
0
),
...
...
@@ -2378,7 +2385,8 @@ reconnect done to recover from failed read");
}
flush_master_info
(
mi
);
if
(
mi
->
rli
.
log_space_limit
&&
mi
->
rli
.
log_space_limit
<
mi
->
rli
.
log_space_total
)
mi
->
rli
.
log_space_total
&&
!
mi
->
rli
.
ignore_log_space_limit
)
if
(
wait_for_relay_log_space
(
&
mi
->
rli
))
{
sql_print_error
(
"Slave I/O thread aborted while waiting for relay \
...
...
@@ -2491,6 +2499,10 @@ extern "C" pthread_handler_decl(handle_slave_sql,arg)
pthread_cond_broadcast
(
&
rli
->
start_cond
);
// This should always be set to 0 when the slave thread is started
rli
->
pending
=
0
;
//tell the I/O thread to take relay_log_space_limit into account from now on
rli
->
ignore_log_space_limit
=
0
;
if
(
init_relay_log_pos
(
rli
,
rli
->
relay_log_name
,
rli
->
relay_log_pos
,
...
...
@@ -3199,11 +3211,41 @@ Log_event* next_event(RELAY_LOG_INFO* rli)
update. If we do not, show slave status will block
*/
pthread_mutex_unlock
(
&
rli
->
data_lock
);
/* Note that wait_for_update unlocks lock_log ! */
rli
->
relay_log
.
wait_for_update
(
rli
->
sql_thd
);
// re-acquire data lock since we released it earlier
pthread_mutex_lock
(
&
rli
->
data_lock
);
/*
Possible deadlock :
- the I/O thread has reached log_space_limit
- the SQL thread has read all relay logs, but cannot purge for some
reason:
* it has already purged all logs except the current one
* there are other logs than the current one but they're involved in
a transaction that finishes in the current one (or is not finished)
Solution :
Wake up the possibly waiting I/O thread, and set a boolean asking
the I/O thread to temporarily ignore the log_space_limit
constraint, because we do not want the I/O thread to block because of
space (it's ok if it blocks for any other reason (e.g. because the
master does not send anything). Then the I/O thread stops waiting
and reads more events.
The SQL thread decides when the I/O thread should take log_space_limit
into account again : ignore_log_space_limit is reset to 0
in purge_first_log (when the SQL thread purges the just-read relay
log), and also when the SQL thread starts. We should also reset
ignore_log_space_limit to 0 when the user does RESET SLAVE, but in
fact, no need as RESET SLAVE requires that the slave
be stopped, and when the SQL thread is later restarted
ignore_log_space_limit will be reset to 0.
*/
pthread_mutex_lock
(
&
rli
->
log_space_lock
);
// prevent the I/O thread from blocking next times
rli
->
ignore_log_space_limit
=
1
;
// If the I/O thread is blocked, unblock it
pthread_cond_broadcast
(
&
rli
->
log_space_cond
);
pthread_mutex_unlock
(
&
rli
->
log_space_lock
);
// Note that wait_for_update unlocks lock_log !
rli
->
relay_log
.
wait_for_update
(
rli
->
sql_thd
);
// re-acquire data lock since we released it earlier
pthread_mutex_lock
(
&
rli
->
data_lock
);
continue
;
}
/*
...
...
sql/slave.h
View file @
b883a9c0
...
...
@@ -156,7 +156,14 @@ typedef struct st_relay_log_info
extra offset to be added to the position.
*/
ulonglong
relay_log_pos
,
pending
;
/*
Handling of the relay_log_space_limit optional constraint.
ignore_log_space_limit is used to resolve a deadlock between I/O and SQL
threads, it makes the I/O thread temporarily forget about the constraint
*/
ulonglong
log_space_limit
,
log_space_total
;
bool
ignore_log_space_limit
;
/*
InnoDB internally stores the master log position it has processed
...
...
sql/sql_class.cc
View file @
b883a9c0
...
...
@@ -186,7 +186,7 @@ THD::THD():user_time(0), is_fatal_error(0),
*/
{
pthread_mutex_lock
(
&
LOCK_thread_count
);
ulong
tmp
=
(
ulong
)
(
rnd
(
&
sql_rand
)
*
0xffffffff
);
/* make all bits random */
ulong
tmp
=
(
ulong
)
(
my_
rnd
(
&
sql_rand
)
*
0xffffffff
);
/* make all bits random */
pthread_mutex_unlock
(
&
LOCK_thread_count
);
randominit
(
&
rand
,
tmp
+
(
ulong
)
&
rand
,
tmp
+
(
ulong
)
::
query_id
);
}
...
...
sql/sql_crypt.cc
View file @
b883a9c0
...
...
@@ -46,7 +46,7 @@ void SQL_CRYPT::crypt_init(ulong *rand_nr)
for
(
i
=
0
;
i
<=
255
;
i
++
)
{
int
idx
=
(
uint
)
(
rnd
(
&
rand
)
*
255.0
);
int
idx
=
(
uint
)
(
my_
rnd
(
&
rand
)
*
255.0
);
char
a
=
decode_buff
[
idx
];
decode_buff
[
idx
]
=
decode_buff
[
i
];
decode_buff
[
+
i
]
=
a
;
...
...
@@ -62,7 +62,7 @@ void SQL_CRYPT::encode(char *str,uint length)
{
for
(
uint
i
=
0
;
i
<
length
;
i
++
)
{
shift
^=
(
uint
)
(
rnd
(
&
rand
)
*
255.0
);
shift
^=
(
uint
)
(
my_
rnd
(
&
rand
)
*
255.0
);
uint
idx
=
(
uint
)
(
uchar
)
str
[
0
];
*
str
++
=
(
char
)
((
uchar
)
encode_buff
[
idx
]
^
shift
);
shift
^=
idx
;
...
...
@@ -74,7 +74,7 @@ void SQL_CRYPT::decode(char *str,uint length)
{
for
(
uint
i
=
0
;
i
<
length
;
i
++
)
{
shift
^=
(
uint
)
(
rnd
(
&
rand
)
*
255.0
);
shift
^=
(
uint
)
(
my_
rnd
(
&
rand
)
*
255.0
);
uint
idx
=
(
uint
)
((
unsigned
char
)
str
[
0
]
^
shift
);
*
str
=
decode_buff
[
idx
];
shift
^=
(
uint
)
(
uchar
)
*
str
++
;
...
...
sql/sql_parse.cc
View file @
b883a9c0
...
...
@@ -563,7 +563,10 @@ check_connections(THD *thd)
thd
->
host
=
ip_to_hostname
(
&
thd
->
remote
.
sin_addr
,
&
connect_errors
);
/* Cut very long hostnames to avoid possible overflows */
if
(
thd
->
host
)
{
thd
->
host
[
min
(
strlen
(
thd
->
host
),
HOSTNAME_LENGTH
)]
=
0
;
thd
->
host_or_ip
=
thd
->
host
;
}
if
(
connect_errors
>
max_connect_errors
)
return
(
ER_HOST_IS_BLOCKED
);
}
...
...
sql/sql_repl.cc
View file @
b883a9c0
...
...
@@ -900,22 +900,21 @@ int change_master(THD* thd, MASTER_INFO* mi)
if
(
lex_mi
->
relay_log_name
)
{
need_relay_log_purge
=
0
;
mi
->
rli
.
skip_log_purge
=
1
;
need_relay_log_purge
=
0
;
strmake
(
mi
->
rli
.
relay_log_name
,
lex_mi
->
relay_log_name
,
sizeof
(
mi
->
rli
.
relay_log_name
)
-
1
);
}
if
(
lex_mi
->
relay_log_pos
)
{
need_relay_log_purge
=
0
;
need_relay_log_purge
=
0
;
mi
->
rli
.
relay_log_pos
=
lex_mi
->
relay_log_pos
;
}
flush_master_info
(
mi
);
if
(
need_relay_log_purge
)
{
mi
->
rli
.
skip_log_purge
=
0
;
mi
->
rli
.
skip_log_purge
=
0
;
thd
->
proc_info
=
"purging old relay logs"
;
if
(
purge_relay_logs
(
&
mi
->
rli
,
thd
,
0
/* not only reset, but also reinit */
,
...
...
@@ -929,6 +928,7 @@ int change_master(THD* thd, MASTER_INFO* mi)
else
{
const
char
*
msg
;
mi
->
rli
.
skip_log_purge
=
1
;
/* Relay log is already initialized */
if
(
init_relay_log_pos
(
&
mi
->
rli
,
mi
->
rli
.
relay_log_name
,
...
...
sql/sql_show.cc
View file @
b883a9c0
...
...
@@ -1334,10 +1334,10 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
{
if
((
thd_info
->
host
=
thd
->
alloc
(
LIST_PROCESS_HOST_LEN
+
1
)))
my_snprintf
((
char
*
)
thd_info
->
host
,
LIST_PROCESS_HOST_LEN
,
"%s:%u"
,
t
hd
->
host_or_ip
,
tmp
->
peer_port
);
"%s:%u"
,
t
mp
->
host_or_ip
,
tmp
->
peer_port
);
}
else
thd_info
->
host
=
thd
->
strdup
(
t
hd
->
host_or_ip
);
thd_info
->
host
=
thd
->
strdup
(
t
mp
->
host_or_ip
);
if
((
thd_info
->
db
=
tmp
->
db
))
// Safe test
thd_info
->
db
=
thd
->
strdup
(
thd_info
->
db
);
thd_info
->
command
=
(
int
)
tmp
->
command
;
...
...
sql/sql_update.cc
View file @
b883a9c0
...
...
@@ -23,6 +23,8 @@
#include "sql_acl.h"
#include "sql_select.h"
static
bool
safe_update_on_fly
(
JOIN_TAB
*
join_tab
,
List
<
Item
>
*
fields
);
/* Return 0 if row hasn't changed */
static
bool
compare_record
(
TABLE
*
table
,
ulong
query_id
)
...
...
@@ -547,11 +549,12 @@ int multi_update::prepare(List<Item> ¬_used_values, SELECT_LEX_UNIT *unit)
/*
Store first used table in main_table as this should be updated first
This is because we know that no row in this table will be read twice.
Initialize table for multi table
Create temporary tables to store changed values for all other tables
that are updated.
IMPLEMENTATION
- Update first table in join on the fly, if possible
- Create temporary tables to store changed values for all other tables
that are updated (and main_table if the above doesn't hold).
*/
bool
...
...
@@ -565,53 +568,113 @@ multi_update::initialize_tables(JOIN *join)
main_table
=
join
->
join_tab
->
table
;
trans_safe
=
transactional_tables
=
main_table
->
file
->
has_transactions
();
log_delayed
=
trans_safe
||
main_table
->
tmp_table
!=
NO_TMP_TABLE
;
table_to_update
=
(
main_table
->
file
->
table_flags
()
&
HA_NOT_MULTI_UPDATE
)
?
(
TABLE
*
)
0
:
main_table
;
/* Create a temporary table for
all tables after
except main table */
table_to_update
=
0
;
/* Create a temporary table for
keys to all tables,
except main table */
for
(
table_ref
=
update_tables
;
table_ref
;
table_ref
=
table_ref
->
next
)
{
TABLE
*
table
=
table_ref
->
table
;
if
(
table
!=
table_to_update
)
{
uint
cnt
=
table_ref
->
shared
;
ORDER
group
;
List
<
Item
>
temp_fields
=
*
fields_for_table
[
cnt
];
TMP_TABLE_PARAM
*
tmp_param
=
tmp_table_param
+
cnt
;
/*
Create a temporary table to store all fields that are changed for this
table. The first field in the temporary table is a pointer to the
original row so that we can find and update it
*/
/* ok to be on stack as this is not referenced outside of this func */
Field_string
offset
(
table
->
file
->
ref_length
,
0
,
"offset"
,
table
,
&
my_charset_bin
);
if
(
temp_fields
.
push_front
(
new
Item_field
(((
Field
*
)
&
offset
))))
DBUG_RETURN
(
1
);
uint
cnt
=
table_ref
->
shared
;
List
<
Item
>
temp_fields
=
*
fields_for_table
[
cnt
];
ORDER
group
;
/* Make an unique key over the first field to avoid duplicated updates */
bzero
((
char
*
)
&
group
,
sizeof
(
group
));
group
.
asc
=
1
;
group
.
item
=
(
Item
**
)
temp_fields
.
head_ref
();
tmp_param
->
quick_group
=
1
;
tmp_param
->
field_count
=
temp_fields
.
elements
;
tmp_param
->
group_parts
=
1
;
tmp_param
->
group_length
=
table
->
file
->
ref_length
;
if
(
!
(
tmp_tables
[
cnt
]
=
create_tmp_table
(
thd
,
tmp_param
,
temp_fields
,
(
ORDER
*
)
&
group
,
0
,
0
,
TMP_TABLE_ALL_COLUMNS
,
HA_POS_ERROR
)))
DBUG_RETURN
(
1
);
tmp_tables
[
cnt
]
->
file
->
extra
(
HA_EXTRA_WRITE_CACHE
);
if
(
table
==
main_table
)
// First table in join
{
if
(
safe_update_on_fly
(
join
->
join_tab
,
&
temp_fields
))
{
table_to_update
=
main_table
;
// Update table on the fly
continue
;
}
}
TMP_TABLE_PARAM
*
tmp_param
=
tmp_table_param
+
cnt
;
/*
Create a temporary table to store all fields that are changed for this
table. The first field in the temporary table is a pointer to the
original row so that we can find and update it
*/
/* ok to be on stack as this is not referenced outside of this func */
Field_string
offset
(
table
->
file
->
ref_length
,
0
,
"offset"
,
table
,
1
,
&
my_charset_bin
);
if
(
temp_fields
.
push_front
(
new
Item_field
(((
Field
*
)
&
offset
))))
DBUG_RETURN
(
1
);
/* Make an unique key over the first field to avoid duplicated updates */
bzero
((
char
*
)
&
group
,
sizeof
(
group
));
group
.
asc
=
1
;
group
.
item
=
(
Item
**
)
temp_fields
.
head_ref
();
tmp_param
->
quick_group
=
1
;
tmp_param
->
field_count
=
temp_fields
.
elements
;
tmp_param
->
group_parts
=
1
;
tmp_param
->
group_length
=
table
->
file
->
ref_length
;
if
(
!
(
tmp_tables
[
cnt
]
=
create_tmp_table
(
thd
,
tmp_param
,
temp_fields
,
(
ORDER
*
)
&
group
,
0
,
0
,
TMP_TABLE_ALL_COLUMNS
,
HA_POS_ERROR
)))
DBUG_RETURN
(
1
);
tmp_tables
[
cnt
]
->
file
->
extra
(
HA_EXTRA_WRITE_CACHE
);
}
DBUG_RETURN
(
0
);
}
/*
Check if table is safe to update on fly
SYNOPSIS
safe_update_on_fly
join_tab How table is used in join
fields Fields that are updated
NOTES
We can update the first table in join on the fly if we know that
a row in this tabel will never be read twice. This is true under
the folloing conditions:
- We are doing a table scan and the data is in a separate file (MyISAM) or
if we don't update a clustered key.
- We are doing a range scan and we don't update the scan key or
the primary key for a clustered table handler.
WARNING
This code is a bit dependent of how make_join_readinfo() works.
RETURN
0 Not safe to update
1 Safe to update
*/
static
bool
safe_update_on_fly
(
JOIN_TAB
*
join_tab
,
List
<
Item
>
*
fields
)
{
TABLE
*
table
=
join_tab
->
table
;
switch
(
join_tab
->
type
)
{
case
JT_SYSTEM
:
case
JT_CONST
:
case
JT_EQ_REF
:
return
1
;
// At most one matching row
case
JT_REF
:
return
!
check_if_key_used
(
table
,
join_tab
->
ref
.
key
,
*
fields
);
case
JT_ALL
:
/* If range search on index */
if
(
join_tab
->
quick
)
return
!
check_if_key_used
(
table
,
join_tab
->
quick
->
index
,
*
fields
);
/* If scanning in clustered key */
if
((
table
->
file
->
table_flags
()
&
HA_PRIMARY_KEY_IN_READ_INDEX
)
&&
table
->
primary_key
<
MAX_KEY
)
return
!
check_if_key_used
(
table
,
table
->
primary_key
,
*
fields
);
return
1
;
default:
break
;
// Avoid compler warning
}
return
0
;
}
multi_update
::~
multi_update
()
{
...
...
sql/sql_yacc.yy
View file @
b883a9c0
...
...
@@ -283,6 +283,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token MAX_UPDATES_PER_HOUR
%token MEDIUM_SYM
%token MERGE_SYM
%token MEMORY_SYM
%token MIN_ROWS
%token MYISAM_SYM
%token NAMES_SYM
...
...
@@ -1009,6 +1010,7 @@ table_types:
| MYISAM_SYM { $$= DB_TYPE_MYISAM; }
| MERGE_SYM { $$= DB_TYPE_MRG_MYISAM; }
| HEAP_SYM { $$= DB_TYPE_HEAP; }
| MEMORY_SYM { $$= DB_TYPE_HEAP; }
| BERKELEY_DB_SYM { $$= DB_TYPE_BERKELEY_DB; }
| INNOBASE_SYM { $$= DB_TYPE_INNODB; };
...
...
@@ -4088,6 +4090,7 @@ keyword:
| MAX_UPDATES_PER_HOUR {}
| MEDIUM_SYM {}
| MERGE_SYM {}
| MEMORY_SYM {}
| MINUTE_SYM {}
| MIN_ROWS {}
| MODIFY_SYM {}
...
...
sql/table.cc
View file @
b883a9c0
...
...
@@ -1245,7 +1245,7 @@ bool check_table_name(const char *name, uint length)
}
}
#endif
if
(
*
name
==
'/'
||
*
name
==
FN_LIBCHAR
||
*
name
==
FN_EXTCHAR
)
if
(
*
name
==
'/'
||
*
name
==
'\\'
||
*
name
==
FN_EXTCHAR
)
return
1
;
name
++
;
}
...
...
strings/strto.c
View file @
b883a9c0
...
...
@@ -35,6 +35,8 @@
it can be compiled with the UNSIGNED and/or LONGLONG flag set
*/
#define strtoll glob_strtoll
/* Fix for True64 */
#include <my_global.h>
#include "m_string.h"
#include "m_ctype.h"
...
...
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