Merge perch.ndb.mysql.com:/home/jonas/src/mysql-5.1-new-ndb

into  perch.ndb.mysql.com:/home/jonas/src/51-work
This commit is contained in:
jonas@perch.ndb.mysql.com 2006-08-14 13:59:25 +02:00
commit f6f5f475ea
71 changed files with 1239 additions and 5194 deletions

View file

@ -2316,12 +2316,16 @@ then
man_dirs="man"
man1_files=`ls -1 $srcdir/man/*.1 | sed -e 's;^.*man/;;'`
man1_files=`echo $man1_files`
man8_files=`ls -1 $srcdir/man/*.8 | sed -e 's;^.*man/;;'`
man8_files=`echo $man8_files`
else
man_dirs=""
man1_files=""
man8_files=""
fi
AC_SUBST(man_dirs)
AC_SUBST(man1_files)
AC_SUBST(man8_files)
# Don't build readline, i have it already
AC_ARG_WITH(readline,

View file

@ -103,7 +103,7 @@ enum Constants
MAX_ALGO_SIZE = 9,
MAX_DIGEST_SZ = 25, // SHA + enum(Bit or Octet) + length(4)
DSA_SIG_SZ = 40,
NAME_MAX = 512 // max total of all included names
ASN_NAME_MAX = 512 // max total of all included names
};
@ -216,7 +216,7 @@ enum { SHA_SIZE = 20 };
// A Signing Authority
class Signer {
PublicKey key_;
char name_[NAME_MAX];
char name_[ASN_NAME_MAX];
byte hash_[SHA_SIZE];
public:
Signer(const byte* k, word32 kSz, const char* n, const byte* h);
@ -270,8 +270,8 @@ private:
byte subjectHash_[SHA_SIZE]; // hash of all Names
byte issuerHash_[SHA_SIZE]; // hash of all Names
byte* signature_;
char issuer_[NAME_MAX]; // Names
char subject_[NAME_MAX]; // Names
char issuer_[ASN_NAME_MAX]; // Names
char subject_[ASN_NAME_MAX]; // Names
char beforeDate_[MAX_DATE_SZ]; // valid before date
char afterDate_[MAX_DATE_SZ]; // valid after date
bool verify_; // Default to yes, but could be off

View file

@ -665,7 +665,7 @@ void CertDecoder::GetName(NameType nt)
SHA sha;
word32 length = GetSequence(); // length of all distinguished names
assert (length < NAME_MAX);
assert (length < ASN_NAME_MAX);
length += source_.get_index();
char* ptr = (nt == ISSUER) ? issuer_ : subject_;

View file

@ -370,8 +370,9 @@ enum ha_base_keytype {
would lead to a duplicate key
error in some other table. */
#define HA_ERR_TABLE_NEEDS_UPGRADE 164 /* The table changed in storage engine */
#define HA_ERR_TABLE_READONLY 165 /* The table is not writable */
#define HA_ERR_LAST 164 /*Copy last error nr.*/
#define HA_ERR_LAST 165 /*Copy last error nr.*/
/* Add error numbers before HA_ERR_LAST and change it accordingly. */
#define HA_ERR_ERRORS (HA_ERR_LAST - HA_ERR_FIRST + 1)

View file

@ -894,10 +894,14 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
}
else
{
uint max_char_len;
/* With conversion */
client_field->charsetnr= thd_cs->number;
uint char_len= server_field.length / item->collation.collation->mbmaxlen;
client_field->length= char_len * thd_cs->mbmaxlen;
max_char_len= (server_field.type >= (int) MYSQL_TYPE_TINY_BLOB &&
server_field.type <= (int) MYSQL_TYPE_BLOB) ?
server_field.length / item->collation.collation->mbminlen :
server_field.length / item->collation.collation->mbmaxlen;
client_field->length= max_char_len * thd_cs->mbmaxlen;
}
client_field->type= server_field.type;
client_field->flags= server_field.flags;

View file

@ -18,7 +18,8 @@
## Process this file with automake to create Makefile.in
man1_MANS = @man1_files@
EXTRA_DIST = $(man1_MANS)
man8_MANS = @man8_files@
EXTRA_DIST = $(man1_MANS) $(man8_MANS)
# Don't update the files from bitkeeper
%::SCCS/s.%

View file

@ -276,7 +276,7 @@ select * from t1;
N M
3 0
delete P1.*,p2.* from `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS p2 ON P1.N = p2.N;
ERROR HY000: The target table p2 of the DELETE is not updatable
ERROR 42S02: Unknown table 'p2' in MULTI DELETE
delete P1.* from `t1` AS P1 INNER JOIN (SELECT aaa FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N;
ERROR 42S22: Unknown column 'aaa' in 'field list'
drop table t1;

View file

@ -1603,6 +1603,44 @@ fld_cid fld_name fld_parentid fld_delt
5 Torkel 0 0
DROP TABLE federated.t1;
DROP TABLE federated.bug_17377_table;
DROP TABLE IF EXISTS federated.test;
CREATE TABLE federated.test (
`id` int(11) NOT NULL,
`val1` varchar(255) NOT NULL,
`val2` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
DROP TABLE IF EXISTS federated.test_local;
DROP TABLE IF EXISTS federated.test_remote;
CREATE TABLE federated.test_local (
`id` int(11) NOT NULL,
`val1` varchar(255) NOT NULL,
`val2` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO federated.test_local VALUES (1, 'foo', 'bar'),
(2, 'bar', 'foo');
CREATE TABLE federated.test_remote (
`id` int(11) NOT NULL,
`val1` varchar(255) NOT NULL,
`val2` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=FEDERATED DEFAULT CHARSET=latin1
CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/test';
insert into federated.test_remote select * from federated.test_local;
select * from federated.test_remote;
id val1 val2
1 foo bar
2 bar foo
delete from federated.test_remote where id in (1,2);
insert into federated.test_remote select * from federated.test_local;
select * from federated.test_remote;
id val1 val2
2 bar foo
1 foo bar
DROP TABLE federated.test_local;
DROP TABLE federated.test_remote;
DROP TABLE federated.test;
drop table if exists federated.t1;
create table federated.t1 (a int, b int, c int);
drop table if exists federated.t1;
@ -1733,6 +1771,19 @@ id val
2 0
drop table t1;
drop table t1;
create table t1 (a longblob not null);
create table t1
(a longblob not null) engine=federated
connection='mysql://root@127.0.0.1:SLAVE_PORT/test/t1';
insert into t1 values (repeat('a',5000));
select length(a) from t1;
length(a)
5000
select length(a) from t1;
length(a)
5000
drop table t1;
drop table t1;
End of 5.0 tests
DROP TABLE IF EXISTS federated.t1;
DROP DATABASE IF EXISTS federated;

View file

@ -758,6 +758,13 @@ select monthname(str_to_date(null, '%m')), monthname(str_to_date(null, '%m')),
monthname(str_to_date(1, '%m')), monthname(str_to_date(0, '%m'));
monthname(str_to_date(null, '%m')) monthname(str_to_date(null, '%m')) monthname(str_to_date(1, '%m')) monthname(str_to_date(0, '%m'))
NULL NULL January NULL
set time_zone='-6:00';
create table t1(a timestamp);
insert into t1 values (19691231190001);
select * from t1;
a
1969-12-31 19:00:01
drop table t1;
create table t1(f1 date, f2 time, f3 datetime);
insert into t1 values ("2006-01-01", "12:01:01", "2006-01-01 12:01:01");
insert into t1 values ("2006-01-02", "12:01:02", "2006-01-02 12:01:02");

View file

@ -72,3 +72,149 @@ sleep(2)
select * from mysql.slow_log;
start_time user_host query_time lock_time rows_sent rows_examined db last_insert_id insert_id server_id sql_text
TIMESTAMP USER_HOST QUERY_TIME 00:00:00 1 0 test 0 0 1 select sleep(2)
alter table mysql.general_log engine=myisam;
ERROR HY000: You can't alter a log table if logging is enabled
alter table mysql.slow_log engine=myisam;
ERROR HY000: You can't alter a log table if logging is enabled
drop table mysql.general_log;
ERROR HY000: Cannot drop log table if log is enabled
drop table mysql.slow_log;
ERROR HY000: Cannot drop log table if log is enabled
set global general_log='OFF';
alter table mysql.slow_log engine=myisam;
ERROR HY000: You can't alter a log table if logging is enabled
set global slow_query_log='OFF';
show create table mysql.general_log;
Table Create Table
general_log CREATE TABLE `general_log` (
`event_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`user_host` mediumtext,
`thread_id` int(11) DEFAULT NULL,
`server_id` int(11) DEFAULT NULL,
`command_type` varchar(64) DEFAULT NULL,
`argument` mediumtext
) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='General log'
show create table mysql.slow_log;
Table Create Table
slow_log CREATE TABLE `slow_log` (
`start_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`user_host` mediumtext NOT NULL,
`query_time` time NOT NULL,
`lock_time` time NOT NULL,
`rows_sent` int(11) NOT NULL,
`rows_examined` int(11) NOT NULL,
`db` varchar(512) DEFAULT NULL,
`last_insert_id` int(11) DEFAULT NULL,
`insert_id` int(11) DEFAULT NULL,
`server_id` int(11) DEFAULT NULL,
`sql_text` mediumtext NOT NULL
) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='Slow log'
alter table mysql.general_log engine=myisam;
alter table mysql.slow_log engine=myisam;
Warnings:
Warning 1264 Out of range value for column 'last_insert_id' at row 0
Warning 1264 Out of range value for column 'insert_id' at row 0
show create table mysql.general_log;
Table Create Table
general_log CREATE TABLE `general_log` (
`event_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`user_host` mediumtext,
`thread_id` int(11) DEFAULT NULL,
`server_id` int(11) DEFAULT NULL,
`command_type` varchar(64) DEFAULT NULL,
`argument` mediumtext
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='General log'
show create table mysql.slow_log;
Table Create Table
slow_log CREATE TABLE `slow_log` (
`start_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`user_host` mediumtext NOT NULL,
`query_time` time NOT NULL,
`lock_time` time NOT NULL,
`rows_sent` int(11) NOT NULL,
`rows_examined` int(11) NOT NULL,
`db` varchar(512) DEFAULT NULL,
`last_insert_id` int(11) DEFAULT NULL,
`insert_id` int(11) DEFAULT NULL,
`server_id` int(11) DEFAULT NULL,
`sql_text` mediumtext NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Slow log'
set global general_log='ON';
set global slow_query_log='ON';
select * from mysql.general_log;
event_time user_host thread_id server_id command_type argument
TIMESTAMP USER_HOST THREAD_ID 1 Query set names utf8
TIMESTAMP USER_HOST THREAD_ID 1 Query create table bug16905 (s char(15) character set utf8 default 'пусто')
TIMESTAMP USER_HOST THREAD_ID 1 Query insert into bug16905 values ('новое')
TIMESTAMP USER_HOST THREAD_ID 1 Query select * from mysql.general_log
TIMESTAMP USER_HOST THREAD_ID 1 Query drop table bug16905
TIMESTAMP USER_HOST THREAD_ID 1 Query truncate table mysql.slow_log
TIMESTAMP USER_HOST THREAD_ID 1 Query set session long_query_time=1
TIMESTAMP USER_HOST THREAD_ID 1 Query select sleep(2)
TIMESTAMP USER_HOST THREAD_ID 1 Query select * from mysql.slow_log
TIMESTAMP USER_HOST THREAD_ID 1 Query alter table mysql.general_log engine=myisam
TIMESTAMP USER_HOST THREAD_ID 1 Query alter table mysql.slow_log engine=myisam
TIMESTAMP USER_HOST THREAD_ID 1 Query drop table mysql.general_log
TIMESTAMP USER_HOST THREAD_ID 1 Query drop table mysql.slow_log
TIMESTAMP USER_HOST THREAD_ID 1 Query set global general_log='OFF'
TIMESTAMP USER_HOST THREAD_ID 1 Query set global slow_query_log='ON'
TIMESTAMP USER_HOST THREAD_ID 1 Query select * from mysql.general_log
flush logs;
lock tables mysql.general_log WRITE;
ERROR HY000: You can't write-lock a log table. Only read access is possible.
lock tables mysql.slow_log WRITE;
ERROR HY000: You can't write-lock a log table. Only read access is possible.
lock tables mysql.general_log READ;
ERROR HY000: You can't use usual read lock with log tables. Try READ LOCAL instead.
lock tables mysql.slow_log READ;
ERROR HY000: You can't use usual read lock with log tables. Try READ LOCAL instead.
lock tables mysql.slow_log READ LOCAL, mysql.general_log READ LOCAL;
unlock tables;
set global general_log='OFF';
set global slow_query_log='OFF';
alter table mysql.slow_log engine=ndb;
ERROR HY000: One can use only CSV and MyISAM engines for the log tables
alter table mysql.slow_log engine=innodb;
ERROR HY000: One can use only CSV and MyISAM engines for the log tables
alter table mysql.slow_log engine=archive;
ERROR HY000: One can use only CSV and MyISAM engines for the log tables
alter table mysql.slow_log engine=blackhole;
ERROR HY000: One can use only CSV and MyISAM engines for the log tables
drop table mysql.slow_log;
drop table mysql.general_log;
drop table mysql.general_log;
ERROR 42S02: Unknown table 'general_log'
drop table mysql.slow_log;
ERROR 42S02: Unknown table 'slow_log'
use mysql;
CREATE TABLE `general_log` (
`event_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP,
`user_host` mediumtext,
`thread_id` int(11) DEFAULT NULL,
`server_id` int(11) DEFAULT NULL,
`command_type` varchar(64) DEFAULT NULL,
`argument` mediumtext
) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='General log';
CREATE TABLE `slow_log` (
`start_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP,
`user_host` mediumtext NOT NULL,
`query_time` time NOT NULL,
`lock_time` time NOT NULL,
`rows_sent` int(11) NOT NULL,
`rows_examined` int(11) NOT NULL,
`db` varchar(512) DEFAULT NULL,
`last_insert_id` int(11) DEFAULT NULL,
`insert_id` int(11) DEFAULT NULL,
`server_id` int(11) DEFAULT NULL,
`sql_text` mediumtext NOT NULL
) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='Slow log';
set global general_log='ON';
set global slow_query_log='ON';
use test;
flush tables with read lock;
unlock tables;
use mysql;
lock tables general_log read local, help_category read local;
unlock tables;

View file

@ -777,3 +777,15 @@ create table tm (b bit(1)) engine = merge union = (t1,t2);
select * from tm;
b
drop table tm, t1, t2;
create table t1 (a int) insert_method = last engine = merge;
insert into t1 values (1);
ERROR HY000: Table 't1' is read only
create table t2 (a int) engine = myisam;
alter table t1 union (t2);
insert into t1 values (1);
alter table t1 insert_method = no;
insert into t1 values (1);
ERROR HY000: Table 't1' is read only
drop table t2;
drop table t1;
End of 5.0 tests

View file

@ -64,17 +64,26 @@ pk u o
insert into t1 values (1,1,1);
drop table t1;
create table t1 (x integer not null primary key, y varchar(32), z integer, key(z)) engine = ndb;
insert into t1 values (1,'one',1), (2,'two',2),(3,"three",3);
insert into t1 values (1,'one',1);
begin;
select * from t1 where x = 1 for update;
x y z
1 one 1
begin;
select * from t1 where x = 1 for update;
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
rollback;
rollback;
insert into t1 values (2,'two',2),(3,"three",3);
begin;
select * from t1 where x = 1 for update;
x y z
1 one 1
select * from t1 where x = 1 for update;
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
select * from t1 where x = 2 for update;
x y z
2 two 2
select * from t1 where x = 1 for update;
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
rollback;
commit;
begin;

View file

@ -286,10 +286,10 @@ INSERT INTO t1 VALUES
(406990,67,'2006-02-23 18:01:45'),(148815,67,'2005-10-25 15:34:17'),
(148812,67,'2005-10-25 15:30:01'),(245651,67,'2005-12-08 15:58:27'),
(154503,67,'2005-10-28 11:52:38');
create table t11 select * from t1 where b = 67 AND (c IS NULL OR c > NOW()) order by 3 asc;
create table t12 select * from t1 where b = 67 AND (c IS NULL OR c > NOW()) order by 3 desc;
create table t11 engine = ndbcluster select * from t1 where b = 67 AND (c IS NULL OR c > NOW()) order by 3 asc;
create table t12 engine = ndbcluster select * from t1 where b = 67 AND (c IS NULL OR c > NOW()) order by 3 desc;
create table t21 select * from t1 where b = 67 AND (c IS NULL OR c > '2005-12-08') order by 3 asc;
create table t22 select * from t1 where b = 67 AND (c IS NULL OR c > '2005-12-08') order by 3 desc;
create table t22 engine = ndbcluster select * from t1 where b = 67 AND (c IS NULL OR c > '2005-12-08') order by 3 desc;
select * from t11 order by 1,2,3;
a b c
254 67 NULL
@ -366,4 +366,65 @@ a b c
406993 67 2006-02-27 11:20:57
406994 67 2006-02-27 11:26:46
406995 67 2006-02-28 11:55:00
select t12.a from t11, t12 where t11.a in(255,256) and t11.a = t12.a and t11.c is null order by t12.a;
a
255
256
update t22 set c = '2005-12-08 15:58:27' where a = 255;
select * from t22 order by 1,2,3;
a b c
1 67 2006-02-23 15:01:35
254 67 NULL
255 67 2005-12-08 15:58:27
256 67 NULL
1120 67 NULL
1133 67 NULL
4101 67 NULL
9199 67 NULL
223456 67 NULL
245651 67 2005-12-08 15:58:27
245652 67 2005-12-08 15:58:27
245653 67 2005-12-08 15:59:07
245654 67 2005-12-08 15:59:08
245655 67 2005-12-08 15:59:08
398340 67 2006-02-20 04:38:53
398341 67 2006-02-20 04:48:44
398545 67 2006-02-20 04:53:13
406631 67 2006-02-23 10:49:42
406988 67 2006-02-23 17:07:22
406989 67 2006-02-23 17:08:46
406990 67 2006-02-23 18:01:45
406991 67 2006-02-24 16:42:32
406992 67 2006-02-24 16:47:18
406993 67 2006-02-27 11:20:57
406994 67 2006-02-27 11:26:46
406995 67 2006-02-28 11:55:00
select t21.* from t21,t22 where t21.a = t22.a and
t22.a in (select t12.a from t11, t12 where t11.a in(255,256) and t11.a = t12.a and t11.c is null) and t22.c is null order by t21.a;
a b c
256 67 NULL
delete from t22 where a > 245651;
update t22 set b = a + 1;
select * from t22 order by 1,2,3;
a b c
1 2 2006-02-23 15:01:35
254 255 NULL
255 256 2005-12-08 15:58:27
256 257 NULL
1120 1121 NULL
1133 1134 NULL
4101 4102 NULL
9199 9200 NULL
223456 223457 NULL
245651 245652 2005-12-08 15:58:27
select c, count(*)
from t21
inner join t22 using (a)
where t22.b in (2,256,257,1121,1134,4102,9200,223457,245652)
group by c
order by c;
c count(*)
NULL 7
2005-12-08 15:58:27 1
2006-02-23 15:01:35 1
DROP TABLE t1, t11, t12, t21, t22;

View file

@ -5051,6 +5051,21 @@ concat('data was: /', var1, '/')
data was: /1/
drop table t3|
drop procedure bug15217|
drop table if exists t3|
drop database if exists mysqltest1|
create table t3 (a int)|
insert into t3 (a) values (1), (2)|
create database mysqltest1|
use mysqltest1|
drop database mysqltest1|
select database()|
database()
NULL
select * from (select 1 as a) as t1 natural join (select * from test.t3) as t2|
a
1
use test|
drop table t3|
drop procedure if exists bug19862|
CREATE TABLE t11 (a INT)|
CREATE TABLE t12 (a INT)|

File diff suppressed because it is too large Load diff

View file

@ -157,7 +157,7 @@ UPDATE `t1` AS P1 INNER JOIN (SELECT aaaa FROM `t1` GROUP BY N HAVING Count(M) >
delete P1.* from `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N;
select * from t1;
--replace_result P2 p2
--error 1288
--error ER_UNKNOWN_TABLE
delete P1.*,P2.* from `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N;
-- error 1054
delete P1.* from `t1` AS P1 INNER JOIN (SELECT aaa FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N;

View file

@ -20,8 +20,8 @@ ndb_autodiscover : BUG#18952 2006-02-16 jmiller Needs to be fixed w.r.t
ndb_autodiscover2 : BUG#18952 2006-02-16 jmiller Needs to be fixed w.r.t binlog
ndb_binlog_ignore_db : BUG#21279 2006-07-25 ingo Randomly throws a warning
ndb_load : BUG#17233 2006-05-04 tomas failed load data from infile causes mysqld dbug_assert, binlog not flushed
ndb_restore_compat : BUG#21283 2006-07-26 ingo Test fails randomly
partition_03ndb : BUG#16385 2006-03-24 mikael Partitions: crash when updating a range partitioned NDB table
ps : BUG#21524 2006-08-08 pgalbraith 'ps' test fails in --ps-protocol test AMD64 bit
ps_7ndb : BUG#18950 2006-02-16 jmiller create table like does not obtain LOCK_open
rpl_ndb_2innodb : BUG#19227 2006-04-20 pekka pk delete apparently not replicated
rpl_ndb_2myisam : BUG#19227 Seems to pass currently

View file

@ -1366,6 +1366,62 @@ drop table federated.t1, federated.t2;
connection master;
--enable_parsing
#
# BUG #18764: Delete conditions causing inconsistencies in Federated tables
#
connection slave;
--disable_warnings
DROP TABLE IF EXISTS federated.test;
--enable_warnings
CREATE TABLE federated.test (
`id` int(11) NOT NULL,
`val1` varchar(255) NOT NULL,
`val2` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
connection master;
--disable_warnings
DROP TABLE IF EXISTS federated.test_local;
DROP TABLE IF EXISTS federated.test_remote;
--enable_warnings
CREATE TABLE federated.test_local (
`id` int(11) NOT NULL,
`val1` varchar(255) NOT NULL,
`val2` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO federated.test_local VALUES (1, 'foo', 'bar'),
(2, 'bar', 'foo');
--replace_result $SLAVE_MYPORT SLAVE_PORT
eval CREATE TABLE federated.test_remote (
`id` int(11) NOT NULL,
`val1` varchar(255) NOT NULL,
`val2` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=FEDERATED DEFAULT CHARSET=latin1
CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/test';
insert into federated.test_remote select * from federated.test_local;
select * from federated.test_remote;
delete from federated.test_remote where id in (1,2);
insert into federated.test_remote select * from federated.test_local;
select * from federated.test_remote;
--disable_warnings
DROP TABLE federated.test_local;
DROP TABLE federated.test_remote;
--enable_warnings
connection slave;
--disable_warnings
DROP TABLE federated.test;
--enable_warnings
#
# Additional test for bug#18437 "Wrong values inserted with a before
# update trigger on NDB table". SQL-layer didn't properly inform
@ -1479,7 +1535,23 @@ drop table t1;
connection master;
drop table t1;
#
# Bug #17608: String literals lost during INSERT query on FEDERATED table
#
connection slave;
create table t1 (a longblob not null);
connection master;
--replace_result $SLAVE_MYPORT SLAVE_PORT
eval create table t1
(a longblob not null) engine=federated
connection='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/t1';
insert into t1 values (repeat('a',5000));
select length(a) from t1;
connection slave;
select length(a) from t1;
drop table t1;
connection master;
drop table t1;
--echo End of 5.0 tests
source include/federated_cleanup.inc;

View file

@ -375,6 +375,16 @@ select last_day('2005-01-00');
select monthname(str_to_date(null, '%m')), monthname(str_to_date(null, '%m')),
monthname(str_to_date(1, '%m')), monthname(str_to_date(0, '%m'));
#
# Bug #16327: problem with timestamp < 1970
#
set time_zone='-6:00';
create table t1(a timestamp);
insert into t1 values (19691231190001);
select * from t1;
drop table t1;
#
# Bug#16377 result of DATE/TIME functions were compared as strings which
# can lead to a wrong result.

View file

@ -171,6 +171,149 @@ select sleep(2);
--replace_column 1 TIMESTAMP 2 USER_HOST 3 QUERY_TIME
select * from mysql.slow_log;
#
# Bug #18559 log tables cannot change engine, and gets deadlocked when
# dropping w/ log on
#
# check that appropriate error messages are given when one attempts to alter
# or drop a log tables, while corresponding logs are enabled
--error ER_CANT_ALTER_LOG_TABLE
alter table mysql.general_log engine=myisam;
--error ER_CANT_ALTER_LOG_TABLE
alter table mysql.slow_log engine=myisam;
--error ER_CANT_DROP_LOG_TABLE
drop table mysql.general_log;
--error ER_CANT_DROP_LOG_TABLE
drop table mysql.slow_log;
# check that one can alter log tables to MyISAM
set global general_log='OFF';
# cannot convert another log table
--error ER_CANT_ALTER_LOG_TABLE
alter table mysql.slow_log engine=myisam;
# alter both tables
set global slow_query_log='OFF';
# check that both tables use CSV engine
show create table mysql.general_log;
show create table mysql.slow_log;
alter table mysql.general_log engine=myisam;
alter table mysql.slow_log engine=myisam;
# check that the tables were converted
show create table mysql.general_log;
show create table mysql.slow_log;
# enable log tables and chek that new tables indeed work
set global general_log='ON';
set global slow_query_log='ON';
--replace_column 1 TIMESTAMP 2 USER_HOST 3 THREAD_ID
select * from mysql.general_log;
# check that flush of myisam-based log tables work fine
flush logs;
# check locking of myisam-based log tables
--error ER_CANT_WRITE_LOCK_LOG_TABLE
lock tables mysql.general_log WRITE;
--error ER_CANT_WRITE_LOCK_LOG_TABLE
lock tables mysql.slow_log WRITE;
#
# This attemts to get TL_READ_NO_INSERT lock, which is incompatible with
# TL_WRITE_CONCURRENT_INSERT. This should fail. We issue this error as log
# tables are always opened and locked by the logger.
#
--error ER_CANT_READ_LOCK_LOG_TABLE
lock tables mysql.general_log READ;
--error ER_CANT_READ_LOCK_LOG_TABLE
lock tables mysql.slow_log READ;
#
# This call should result in TL_READ lock on the log table. This is ok and
# should pass.
#
lock tables mysql.slow_log READ LOCAL, mysql.general_log READ LOCAL;
unlock tables;
# check that we can drop them
set global general_log='OFF';
set global slow_query_log='OFF';
# check that alter table doesn't work for other engines
--error ER_BAD_LOG_ENGINE
alter table mysql.slow_log engine=ndb;
--error ER_BAD_LOG_ENGINE
alter table mysql.slow_log engine=innodb;
--error ER_BAD_LOG_ENGINE
alter table mysql.slow_log engine=archive;
--error ER_BAD_LOG_ENGINE
alter table mysql.slow_log engine=blackhole;
drop table mysql.slow_log;
drop table mysql.general_log;
# check that table share cleanup is performed correctly (double drop)
--error ER_BAD_TABLE_ERROR
drop table mysql.general_log;
--error ER_BAD_TABLE_ERROR
drop table mysql.slow_log;
# recreate tables and enable logs
use mysql;
CREATE TABLE `general_log` (
`event_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP,
`user_host` mediumtext,
`thread_id` int(11) DEFAULT NULL,
`server_id` int(11) DEFAULT NULL,
`command_type` varchar(64) DEFAULT NULL,
`argument` mediumtext
) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='General log';
CREATE TABLE `slow_log` (
`start_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP,
`user_host` mediumtext NOT NULL,
`query_time` time NOT NULL,
`lock_time` time NOT NULL,
`rows_sent` int(11) NOT NULL,
`rows_examined` int(11) NOT NULL,
`db` varchar(512) DEFAULT NULL,
`last_insert_id` int(11) DEFAULT NULL,
`insert_id` int(11) DEFAULT NULL,
`server_id` int(11) DEFAULT NULL,
`sql_text` mediumtext NOT NULL
) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='Slow log';
set global general_log='ON';
set global slow_query_log='ON';
use test;
#
# Bug #20139 Infinite loop after "FLUSH" and "LOCK tabX, general_log"
#
flush tables with read lock;
unlock tables;
use mysql;
lock tables general_log read local, help_category read local;
unlock tables;
# kill all connections
disconnect con1;
disconnect con2;

View file

@ -392,4 +392,19 @@ create table tm (b bit(1)) engine = merge union = (t1,t2);
select * from tm;
drop table tm, t1, t2;
# End of 5.0 tests
#
# Bug #17766: The server accepts to create MERGE tables which cannot work
#
create table t1 (a int) insert_method = last engine = merge;
--error ER_OPEN_AS_READONLY
insert into t1 values (1);
create table t2 (a int) engine = myisam;
alter table t1 union (t2);
insert into t1 values (1);
alter table t1 insert_method = no;
--error ER_OPEN_AS_READONLY
insert into t1 values (1);
drop table t2;
drop table t1;
--echo End of 5.0 tests

View file

@ -51,14 +51,14 @@ select "--- Local --" as "";
select "--- Broken LOAD DATA --" as "";
--enable_query_log
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
--exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ $MYSQLTEST_VARDIR/log/master-bin.000002
--exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ $MYSQLTEST_VARDIR/log/master-bin.000002 2> /dev/null
# this should show almost nothing
--disable_query_log
select "--- --database --" as "";
--enable_query_log
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
--exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ --database=nottest $MYSQLTEST_VARDIR/log/master-bin.000001
--exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ --database=nottest $MYSQLTEST_VARDIR/log/master-bin.000001 2> /dev/null
# this test for position option
--disable_query_log
@ -83,14 +83,14 @@ select "--- Remote --" as "";
select "--- Broken LOAD DATA --" as "";
--enable_query_log
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
--exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000002
--exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000002 2> /dev/null
# And this too ! (altough it is documented)
--disable_query_log
select "--- --database --" as "";
--enable_query_log
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
--exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT --database=nottest master-bin.000001
--exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT --database=nottest master-bin.000001 2> /dev/null
# Strangely but this works
--disable_query_log

View file

@ -2,6 +2,9 @@
-- source include/have_multi_ndb.inc
-- source include/not_embedded.inc
# see bug#21563
-- source include/have_binlog_format_row.inc
--disable_warnings
drop table if exists t1, t2;
--enable_warnings

View file

@ -73,7 +73,7 @@ drop table t1;
create table t1 (x integer not null primary key, y varchar(32), z integer, key(z)) engine = ndb;
insert into t1 values (1,'one',1), (2,'two',2),(3,"three",3);
insert into t1 values (1,'one',1);
# PK access
connection con1;
@ -82,11 +82,22 @@ select * from t1 where x = 1 for update;
connection con2;
begin;
select * from t1 where x = 2 for update;
--error 1205
select * from t1 where x = 1 for update;
rollback;
connection con1;
rollback;
insert into t1 values (2,'two',2),(3,"three",3);
begin;
select * from t1 where x = 1 for update;
connection con2;
--error 1205
select * from t1 where x = 1 for update;
select * from t1 where x = 2 for update;
rollback;
connection con1;
commit;

View file

@ -228,13 +228,32 @@ INSERT INTO t1 VALUES
(148812,67,'2005-10-25 15:30:01'),(245651,67,'2005-12-08 15:58:27'),
(154503,67,'2005-10-28 11:52:38');
create table t11 select * from t1 where b = 67 AND (c IS NULL OR c > NOW()) order by 3 asc;
create table t12 select * from t1 where b = 67 AND (c IS NULL OR c > NOW()) order by 3 desc;
create table t11 engine = ndbcluster select * from t1 where b = 67 AND (c IS NULL OR c > NOW()) order by 3 asc;
create table t12 engine = ndbcluster select * from t1 where b = 67 AND (c IS NULL OR c > NOW()) order by 3 desc;
create table t21 select * from t1 where b = 67 AND (c IS NULL OR c > '2005-12-08') order by 3 asc;
create table t22 select * from t1 where b = 67 AND (c IS NULL OR c > '2005-12-08') order by 3 desc;
create table t22 engine = ndbcluster select * from t1 where b = 67 AND (c IS NULL OR c > '2005-12-08') order by 3 desc;
select * from t11 order by 1,2,3;
select * from t12 order by 1,2,3;
select * from t21 order by 1,2,3;
select * from t22 order by 1,2,3;
# join tests
select t12.a from t11, t12 where t11.a in(255,256) and t11.a = t12.a and t11.c is null order by t12.a;
update t22 set c = '2005-12-08 15:58:27' where a = 255;
select * from t22 order by 1,2,3;
select t21.* from t21,t22 where t21.a = t22.a and
t22.a in (select t12.a from t11, t12 where t11.a in(255,256) and t11.a = t12.a and t11.c is null) and t22.c is null order by t21.a;
delete from t22 where a > 245651;
update t22 set b = a + 1;
select * from t22 order by 1,2,3;
select c, count(*)
from t21
inner join t22 using (a)
where t22.b in (2,256,257,1121,1134,4102,9200,223457,245652)
group by c
order by c;
DROP TABLE t1, t11, t12, t21, t22;

View file

@ -5950,6 +5950,33 @@ call bug15217()|
drop table t3|
drop procedure bug15217|
#
# Bug#21002 "Derived table not selecting from a "real" table fails in JOINs"
#
# A regression caused by the fix for Bug#18444: for derived tables we should
# set an empty string as the current database. They do not belong to any
# database and must be usable even if there is no database
# selected.
--disable_warnings
drop table if exists t3|
drop database if exists mysqltest1|
--enable_warnings
create table t3 (a int)|
insert into t3 (a) values (1), (2)|
create database mysqltest1|
use mysqltest1|
drop database mysqltest1|
# No current database
select database()|
select * from (select 1 as a) as t1 natural join (select * from test.t3) as t2|
use test|
drop table t3|
#
# BUG#19862: Sort with filesort by function evaluates function twice
#
@ -5968,6 +5995,8 @@ SELECT bug19862(a) FROM t12 ORDER BY 1|
SELECT * FROM t11|
DROP TABLE t11, t12|
DROP FUNCTION bug19862|
#
# BUG#NNNN: New bug synopsis
#

View file

@ -1,6 +1,6 @@
--source include/have_udf.inc
#
# To run this tests the "sql/udf_example.cc" need to be compiled into
# To run this tests the "sql/udf_example.c" need to be compiled into
# udf_example.so and LD_LIBRARY_PATH should be setup to point out where
# the library are.
#

View file

@ -98,7 +98,7 @@ mkdir $BASE $BASE/bin $BASE/docs \
if [ $BASE_SYSTEM != "netware" ] ; then
mkdir $BASE/share/mysql $BASE/tests $BASE/man \
$BASE/man/man1 $BASE/data $BASE/data/mysql $BASE/data/test
$BASE/man/man1 $BASE/man/man8 $BASE/data $BASE/data/mysql $BASE/data/test
chmod o-rwx $BASE/data $BASE/data/*
fi
@ -222,6 +222,7 @@ if [ $BASE_SYSTEM != "netware" ] ; then
fi
if [ -d man ] ; then
$CP man/*.1 $BASE/man/man1
$CP man/*.8 $BASE/man/man8
fi
fi
@ -313,6 +314,11 @@ else
rm -f $BASE/README.NW
fi
# Make safe_mysqld a symlink to mysqld_safe for backwards portability
if [ $BASE_SYSTEM != "netware" ] ; then
(cd $BASE/bin ; ln -s mysqld_safe safe_mysqld )
fi
# Clean up if we did this from a bk tree
if [ -d $BASE/share/SCCS ] ; then
find $BASE/share -name SCCS -print | xargs rm -rf

View file

@ -37,7 +37,7 @@
OutputFile="../../client_debug/mysqlmanager.exe"
LinkIncremental="2"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/mysqlmanager.pdb"
ProgramDatabaseFile="../../client_debug/mysqlmanager.pdb"
SubSystem="1"
TargetMachine="1"/>
<Tool

View file

@ -122,7 +122,7 @@ DEFS = -DMYSQL_SERVER \
@DEFS@
BUILT_SOURCES = sql_yacc.cc sql_yacc.h lex_hash.h
EXTRA_DIST = udf_example.cc $(BUILT_SOURCES) \
EXTRA_DIST = udf_example.c $(BUILT_SOURCES) \
nt_servc.cc nt_servc.h message.mc CMakeLists.txt
CLEANFILES = lex_hash.h sql_yacc.cc sql_yacc.h
AM_YFLAGS = -d
@ -176,7 +176,7 @@ handler.o: handler.cc ha_ndbcluster.h
# For testing of udf_example.so
noinst_LTLIBRARIES= udf_example.la
udf_example_la_SOURCES= udf_example.cc
udf_example_la_SOURCES= udf_example.c
udf_example_la_LDFLAGS= -module -rpath $(pkglibdir)

View file

@ -1572,104 +1572,6 @@ Field *Field::new_key_field(MEM_ROOT *root, struct st_table *new_table,
}
/*
SYNOPSIS
Field::quote_data()
unquoted_string Pointer pointing to the value of a field
DESCRIPTION
Simple method that passes the field type to the method "type_quote"
To get a true/false value as to whether the value in string1 needs
to be enclosed with quotes. This ensures that values in the final
sql statement to be passed to the remote server will be quoted properly
RETURN_VALUE
void Immediately - if string doesn't need quote
void Upon prepending/appending quotes on each side of variable
*/
bool Field::quote_data(String *unquoted_string)
{
char escaped_string[IO_SIZE];
DBUG_ENTER("Field::quote_data");
if (!needs_quotes())
DBUG_RETURN(0);
// this is the same call that mysql_real_escape_string() calls
if (escape_string_for_mysql(&my_charset_bin, (char *)escaped_string,
sizeof(escaped_string), unquoted_string->ptr(),
unquoted_string->length()) == (ulong)~0)
DBUG_RETURN(1);
// reset string, then re-append with quotes and escaped values
unquoted_string->length(0);
if (unquoted_string->append('\'') ||
unquoted_string->append((char *)escaped_string) ||
unquoted_string->append('\''))
DBUG_RETURN(1);
DBUG_RETURN(0);
}
/*
Quote a field type if needed
SYNOPSIS
Field::type_quote
DESCRIPTION
Simple method to give true/false whether a field should be quoted.
Used when constructing INSERT and UPDATE queries to the remote server
see write_row and update_row
RETURN VALUE
0 if value is of type NOT needing quotes
1 if value is of type needing quotes
*/
bool Field::needs_quotes(void)
{
DBUG_ENTER("Field::type_quote");
switch (type()) {
//FIX this when kernel is fixed
case MYSQL_TYPE_VARCHAR :
case FIELD_TYPE_STRING :
case FIELD_TYPE_VAR_STRING :
case FIELD_TYPE_YEAR :
case FIELD_TYPE_NEWDATE :
case FIELD_TYPE_TIME :
case FIELD_TYPE_TIMESTAMP :
case FIELD_TYPE_DATE :
case FIELD_TYPE_DATETIME :
case FIELD_TYPE_TINY_BLOB :
case FIELD_TYPE_BLOB :
case FIELD_TYPE_MEDIUM_BLOB :
case FIELD_TYPE_LONG_BLOB :
case FIELD_TYPE_GEOMETRY :
case FIELD_TYPE_BIT:
DBUG_RETURN(1);
case FIELD_TYPE_DECIMAL :
case FIELD_TYPE_TINY :
case FIELD_TYPE_SHORT :
case FIELD_TYPE_INT24 :
case FIELD_TYPE_LONG :
case FIELD_TYPE_FLOAT :
case FIELD_TYPE_DOUBLE :
case FIELD_TYPE_LONGLONG :
case FIELD_TYPE_NULL :
case FIELD_TYPE_SET :
case FIELD_TYPE_ENUM :
DBUG_RETURN(0);
default:
DBUG_RETURN(0);
}
}
/* This is used to generate a field in TABLE from TABLE_SHARE */
Field *Field::clone(MEM_ROOT *root, struct st_table *new_table)
@ -4820,7 +4722,7 @@ String *Field_timestamp::val_str(String *val_buffer, String *val_ptr)
thd->time_zone_used= 1;
temp= time_tmp.year % 100;
if (temp < YY_PART_YEAR)
if (temp < YY_PART_YEAR - 1)
{
*to++= '2';
*to++= '0';

View file

@ -268,8 +268,6 @@ public:
ptr= old_ptr;
return str;
}
bool quote_data(String *unquoted_string);
bool needs_quotes(void);
virtual bool send_binary(Protocol *protocol);
virtual char *pack(char* to, const char *from, uint max_length=~(uint) 0)
{

View file

@ -124,11 +124,6 @@
ha_federated::write_row
<for every field/column>
Field::quote_data
Field::quote_data
</for every field/column>
ha_federated::reset
(UPDATE)
@ -138,20 +133,10 @@
ha_federated::index_init
ha_federated::index_read
ha_federated::index_read_idx
Field::quote_data
ha_federated::rnd_next
ha_federated::convert_row_to_internal_format
ha_federated::update_row
<quote 3 cols, new and old data>
Field::quote_data
Field::quote_data
Field::quote_data
Field::quote_data
Field::quote_data
Field::quote_data
</quote 3 cols, new and old data>
ha_federated::extra
ha_federated::extra
ha_federated::extra
@ -1157,7 +1142,7 @@ bool ha_federated::create_where_from_key(String *to,
Field *field= key_part->field;
uint store_length= key_part->store_length;
uint part_length= min(store_length, length);
needs_quotes= field->needs_quotes();
needs_quotes= 1;
DBUG_DUMP("key, start of loop", (char *) ptr, length);
if (key_part->null_bit)
@ -1578,7 +1563,62 @@ inline uint field_in_record_is_null(TABLE *table,
int ha_federated::write_row(byte *buf)
{
bool has_fields= FALSE;
/*
I need a bool again, in 5.0, I used table->s->fields to accomplish this.
This worked as a flag that says there are fields with values or not.
In 5.1, this value doesn't work the same, and I end up with the code
truncating open parenthesis:
the statement "INSERT INTO t1 VALUES ()" ends up being first built
in two strings
"INSERT INTO t1 ("
and
" VALUES ("
If there are fields with values, they get appended, with commas, and
the last loop, a trailing comma is there
"INSERT INTO t1 ( col1, col2, colN, "
" VALUES ( 'val1', 'val2', 'valN', "
Then, if there are fields, it should decrement the string by ", " length.
"INSERT INTO t1 ( col1, col2, colN"
" VALUES ( 'val1', 'val2', 'valN'"
Then it adds a close paren to both - if there are fields
"INSERT INTO t1 ( col1, col2, colN)"
" VALUES ( 'val1', 'val2', 'valN')"
Then appends both together
"INSERT INTO t1 ( col1, col2, colN) VALUES ( 'val1', 'val2', 'valN')"
So... the problem, is if you have the original statement:
"INSERT INTO t1 VALUES ()"
Which is legitimate, but if the code thinks there are fields
"INSERT INTO t1 ("
" VALUES ( "
If the field flag is set, but there are no commas, reduces the
string by strlen(", ")
"INSERT INTO t1 "
" VALUES "
Then adds the close parenthesis
"INSERT INTO t1 )"
" VALUES )"
So, I have to use a bool as before, set in the loop where fields and commas
are appended to the string
*/
my_bool commas_added= FALSE;
char insert_buffer[FEDERATED_QUERY_BUFFER_SIZE];
char values_buffer[FEDERATED_QUERY_BUFFER_SIZE];
char insert_field_value_buffer[STRING_BUFFER_USUAL_SIZE];
@ -1594,10 +1634,6 @@ int ha_federated::write_row(byte *buf)
&my_charset_bin);
my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->read_set);
DBUG_ENTER("ha_federated::write_row");
DBUG_PRINT("info",
("table charset name %s csname %s",
table->s->table_charset->name,
table->s->table_charset->csname));
values_string.length(0);
insert_string.length(0);
@ -1609,37 +1645,33 @@ int ha_federated::write_row(byte *buf)
/*
start both our field and field values strings
*/
insert_string.append(STRING_WITH_LEN("INSERT `"));
insert_string.append(STRING_WITH_LEN("INSERT INTO `"));
insert_string.append(share->table_name, share->table_name_length);
insert_string.append(STRING_WITH_LEN("` ("));
insert_string.append('`');
insert_string.append(STRING_WITH_LEN(" ("));
values_string.append(STRING_WITH_LEN(" VALUES ("));
values_string.append(STRING_WITH_LEN(" VALUES "));
values_string.append(STRING_WITH_LEN(" ("));
/*
loop through the field pointer array, add any fields to both the values
list and the fields list that is part of the write set
You might ask "Why an index variable (has_fields) ?" My answer is that
we need to count how many fields we actually need
*/
for (field= table->field; *field; field++)
{
/* if there is a query id and if it's equal to the current query id */
if (bitmap_is_set(table->write_set, (*field)->field_index))
{
/*
There are some fields. This will be used later to determine
whether to chop off commas and parens.
*/
has_fields= TRUE;
commas_added= TRUE;
if ((*field)->is_null())
insert_field_value_string.append(STRING_WITH_LEN(" NULL "));
else
{
(*field)->val_str(&insert_field_value_string);
/* quote these fields if they require it */
(*field)->quote_data(&insert_field_value_string);
values_string.append('\'');
insert_field_value_string.print(&values_string);
values_string.append('\'');
insert_field_value_string.length(0);
}
/* append the field name */
insert_string.append((*field)->field_name);
@ -1665,10 +1697,10 @@ int ha_federated::write_row(byte *buf)
AND, we don't want to chop off the last char '('
insert will be "INSERT INTO t1 VALUES ();"
*/
if (has_fields)
if (commas_added)
{
/* chops off trailing commas */
insert_string.length(insert_string.length() - sizeof_trailing_comma);
/* chops off leading commas */
values_string.length(values_string.length() - sizeof_trailing_comma);
insert_string.append(STRING_WITH_LEN(") "));
}
@ -1678,6 +1710,7 @@ int ha_federated::write_row(byte *buf)
insert_string.length(insert_string.length() - sizeof_trailing_closeparen);
}
/* we always want to append this, even if there aren't any fields */
values_string.append(STRING_WITH_LEN(") "));
/* add the values */
@ -1799,6 +1832,7 @@ int ha_federated::update_row(const byte *old_data, byte *new_data)
this.
*/
bool has_a_primary_key= test(table->s->primary_key != MAX_KEY);
/*
buffers for following strings
*/
@ -1844,7 +1878,7 @@ int ha_federated::update_row(const byte *old_data, byte *new_data)
if (bitmap_is_set(table->write_set, (*field)->field_index))
{
update_string.append((*field)->field_name);
update_string.append(STRING_WITH_LEN("="));
update_string.append(STRING_WITH_LEN(" = "));
if ((*field)->is_null())
update_string.append(STRING_WITH_LEN(" NULL "));
@ -1853,8 +1887,9 @@ int ha_federated::update_row(const byte *old_data, byte *new_data)
my_bitmap_map *old_map= tmp_use_all_columns(table, table->read_set);
/* otherwise = */
(*field)->val_str(&field_value);
(*field)->quote_data(&field_value);
update_string.append(field_value);
update_string.append('\'');
field_value.print(&update_string);
update_string.append('\'');
field_value.length(0);
tmp_restore_column_map(table->read_set, old_map);
}
@ -1871,8 +1906,9 @@ int ha_federated::update_row(const byte *old_data, byte *new_data)
where_string.append(STRING_WITH_LEN(" = "));
(*field)->val_str(&field_value,
(char*) (old_data + (*field)->offset()));
(*field)->quote_data(&field_value);
where_string.append(field_value);
where_string.append('\'');
field_value.print(&where_string);
where_string.append('\'');
field_value.length(0);
}
where_string.append(STRING_WITH_LEN(" AND "));
@ -1881,6 +1917,7 @@ int ha_federated::update_row(const byte *old_data, byte *new_data)
/* Remove last ', '. This works as there must be at least on updated field */
update_string.length(update_string.length() - sizeof_trailing_comma);
if (where_string.length())
{
/* chop off trailing AND */
@ -1948,8 +1985,9 @@ int ha_federated::delete_row(const byte *buf)
{
delete_string.append(STRING_WITH_LEN(" = "));
cur_field->val_str(&data_string);
cur_field->quote_data(&data_string);
delete_string.append(data_string);
delete_string.append('\'');
data_string.print(&delete_string);
delete_string.append('\'');
}
delete_string.append(STRING_WITH_LEN(" AND "));
}

View file

@ -274,6 +274,15 @@ bool ha_myisam::check_if_locking_is_allowed(uint sql_command,
table->s->table_name.str);
return FALSE;
}
/*
Deny locking of the log tables, which is incompatible with
concurrent insert. Unless called from a logger THD:
general_log_thd or slow_log_thd.
*/
if (!called_by_logger_thread)
return check_if_log_table_locking_is_allowed(sql_command, type, table);
return TRUE;
}

View file

@ -122,6 +122,10 @@ int ha_myisammrg::close(void)
int ha_myisammrg::write_row(byte * buf)
{
statistic_increment(table->in_use->status_var.ha_write_count,&LOCK_status);
if (file->merge_insert_method == MERGE_INSERT_DISABLED || !file->tables)
return (HA_ERR_TABLE_READONLY);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
table->timestamp_field->set_time();
if (table->next_number_field && buf == table->record[0])

View file

@ -256,13 +256,15 @@ int execute_no_commit_ignore_no_key(ha_ndbcluster *h, NdbTransaction *trans)
}
inline
int execute_no_commit(ha_ndbcluster *h, NdbTransaction *trans)
int execute_no_commit(ha_ndbcluster *h, NdbTransaction *trans,
bool force_release)
{
#ifdef NOT_USED
int m_batch_execute= 0;
if (m_batch_execute)
return 0;
#endif
h->release_completed_operations(trans, force_release);
return h->m_ignore_no_key ?
execute_no_commit_ignore_no_key(h,trans) :
trans->execute(NdbTransaction::NoCommit,
@ -297,13 +299,15 @@ int execute_commit(THD *thd, NdbTransaction *trans)
}
inline
int execute_no_commit_ie(ha_ndbcluster *h, NdbTransaction *trans)
int execute_no_commit_ie(ha_ndbcluster *h, NdbTransaction *trans,
bool force_release)
{
#ifdef NOT_USED
int m_batch_execute= 0;
if (m_batch_execute)
return 0;
#endif
h->release_completed_operations(trans, force_release);
return trans->execute(NdbTransaction::NoCommit,
NdbTransaction::AO_IgnoreError,
h->m_force_send);
@ -328,6 +332,7 @@ Thd_ndb::Thd_ndb()
all= NULL;
stmt= NULL;
error= 0;
query_state&= NDB_QUERY_NORMAL;
options= 0;
(void) hash_init(&open_tables, &my_charset_bin, 5, 0, 0,
(hash_get_key)thd_ndb_share_get_key, 0, 0);
@ -1696,7 +1701,7 @@ int ha_ndbcluster::pk_read(const byte *key, uint key_len, byte *buf,
ERR_RETURN(trans->getNdbError());
}
if (execute_no_commit_ie(this,trans) != 0)
if (execute_no_commit_ie(this,trans,false) != 0)
{
table->status= STATUS_NOT_FOUND;
DBUG_RETURN(ndb_err(trans));
@ -1761,7 +1766,7 @@ int ha_ndbcluster::complemented_read(const byte *old_data, byte *new_data,
}
}
if (execute_no_commit(this,trans) != 0)
if (execute_no_commit(this,trans,false) != 0)
{
table->status= STATUS_NOT_FOUND;
DBUG_RETURN(ndb_err(trans));
@ -1914,7 +1919,7 @@ int ha_ndbcluster::peek_indexed_rows(const byte *record)
}
last= trans->getLastDefinedOperation();
if (first)
res= execute_no_commit_ie(this,trans);
res= execute_no_commit_ie(this,trans,false);
else
{
// Table has no keys
@ -1963,7 +1968,7 @@ int ha_ndbcluster::unique_index_read(const byte *key,
if ((res= define_read_attrs(buf, op)))
DBUG_RETURN(res);
if (execute_no_commit_ie(this,trans) != 0)
if (execute_no_commit_ie(this,trans,false) != 0)
{
table->status= STATUS_NOT_FOUND;
DBUG_RETURN(ndb_err(trans));
@ -2011,7 +2016,7 @@ inline int ha_ndbcluster::fetch_next(NdbScanOperation* cursor)
*/
if (m_ops_pending && m_blobs_pending)
{
if (execute_no_commit(this,trans) != 0)
if (execute_no_commit(this,trans,false) != 0)
DBUG_RETURN(ndb_err(trans));
m_ops_pending= 0;
m_blobs_pending= FALSE;
@ -2043,7 +2048,7 @@ inline int ha_ndbcluster::fetch_next(NdbScanOperation* cursor)
{
if (m_transaction_on)
{
if (execute_no_commit(this,trans) != 0)
if (execute_no_commit(this,trans,false) != 0)
DBUG_RETURN(-1);
}
else
@ -2370,7 +2375,7 @@ int ha_ndbcluster::ordered_index_scan(const key_range *start_key,
ERR_RETURN(trans->getNdbError());
}
if (execute_no_commit(this,trans) != 0)
if (execute_no_commit(this,trans,false) != 0)
DBUG_RETURN(ndb_err(trans));
DBUG_RETURN(next_result(buf));
@ -2440,7 +2445,7 @@ int ha_ndbcluster::full_table_scan(byte *buf)
if ((res= define_read_attrs(buf, op)))
DBUG_RETURN(res);
if (execute_no_commit(this,trans) != 0)
if (execute_no_commit(this,trans,false) != 0)
DBUG_RETURN(ndb_err(trans));
DBUG_PRINT("exit", ("Scan started successfully"));
DBUG_RETURN(next_result(buf));
@ -2603,7 +2608,7 @@ int ha_ndbcluster::write_row(byte *record)
m_bulk_insert_not_flushed= FALSE;
if (m_transaction_on)
{
if (execute_no_commit(this,trans) != 0)
if (execute_no_commit(this,trans,false) != 0)
{
m_skip_auto_increment= TRUE;
no_uncommitted_rows_execute_failure();
@ -2840,7 +2845,7 @@ int ha_ndbcluster::update_row(const byte *old_data, byte *new_data)
op->setValue(no_fields, part_func_value);
}
// Execute update operation
if (!cursor && execute_no_commit(this,trans) != 0) {
if (!cursor && execute_no_commit(this,trans,false) != 0) {
no_uncommitted_rows_execute_failure();
DBUG_RETURN(ndb_err(trans));
}
@ -2926,7 +2931,7 @@ int ha_ndbcluster::delete_row(const byte *record)
}
// Execute delete operation
if (execute_no_commit(this,trans) != 0) {
if (execute_no_commit(this,trans,false) != 0) {
no_uncommitted_rows_execute_failure();
DBUG_RETURN(ndb_err(trans));
}
@ -3392,6 +3397,26 @@ int ha_ndbcluster::close_scan()
NdbScanOperation *cursor= m_active_cursor ? m_active_cursor : m_multi_cursor;
if (m_lock_tuple)
{
/*
Lock level m_lock.type either TL_WRITE_ALLOW_WRITE
(SELECT FOR UPDATE) or TL_READ_WITH_SHARED_LOCKS (SELECT
LOCK WITH SHARE MODE) and row was not explictly unlocked
with unlock_row() call
*/
NdbOperation *op;
// Lock row
DBUG_PRINT("info", ("Keeping lock on scanned row"));
if (!(op= cursor->lockCurrentTuple()))
{
m_lock_tuple= false;
ERR_RETURN(trans->getNdbError());
}
m_ops_pending++;
}
m_lock_tuple= false;
if (m_ops_pending)
{
/*
@ -3399,7 +3424,7 @@ int ha_ndbcluster::close_scan()
deleteing/updating transaction before closing the scan
*/
DBUG_PRINT("info", ("ops_pending: %d", m_ops_pending));
if (execute_no_commit(this,trans) != 0) {
if (execute_no_commit(this,trans,false) != 0) {
no_uncommitted_rows_execute_failure();
DBUG_RETURN(ndb_err(trans));
}
@ -3793,7 +3818,7 @@ int ha_ndbcluster::end_bulk_insert()
m_bulk_insert_not_flushed= FALSE;
if (m_transaction_on)
{
if (execute_no_commit(this, trans) != 0)
if (execute_no_commit(this, trans,false) != 0)
{
no_uncommitted_rows_execute_failure();
my_errno= error= ndb_err(trans);
@ -3968,6 +3993,7 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
ERR_RETURN(ndb->getNdbError());
thd_ndb->init_open_tables();
thd_ndb->stmt= trans;
thd_ndb->query_state&= NDB_QUERY_NORMAL;
trans_register_ha(thd, FALSE, &ndbcluster_hton);
}
else
@ -3983,6 +4009,7 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
ERR_RETURN(ndb->getNdbError());
thd_ndb->init_open_tables();
thd_ndb->all= trans;
thd_ndb->query_state&= NDB_QUERY_NORMAL;
trans_register_ha(thd, TRUE, &ndbcluster_hton);
/*
@ -4139,6 +4166,7 @@ int ha_ndbcluster::start_stmt(THD *thd, thr_lock_type lock_type)
thd_ndb->stmt= trans;
trans_register_ha(thd, FALSE, &ndbcluster_hton);
}
thd_ndb->query_state&= NDB_QUERY_NORMAL;
m_active_trans= trans;
// Start of statement
@ -7572,6 +7600,7 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
NDB_INDEX_TYPE index_type= get_index_type(active_index);
ulong reclength= table_share->reclength;
NdbOperation* op;
Thd_ndb *thd_ndb= get_thd_ndb(current_thd);
if (uses_blob_value())
{
@ -7585,7 +7614,7 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
sorted,
buffer));
}
thd_ndb->query_state|= NDB_QUERY_MULTI_READ_RANGE;
m_disable_multi_read= FALSE;
/**
@ -7757,7 +7786,7 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
*/
m_current_multi_operation=
lastOp ? lastOp->next() : m_active_trans->getFirstDefinedOperation();
if (!(res= execute_no_commit_ie(this, m_active_trans)))
if (!(res= execute_no_commit_ie(this, m_active_trans,true)))
{
m_multi_range_defined= multi_range_curr;
multi_range_curr= ranges;
@ -9558,6 +9587,24 @@ ha_ndbcluster::generate_scan_filter(Ndb_cond_stack *ndb_cond_stack,
DBUG_RETURN(0);
}
void
ha_ndbcluster::release_completed_operations(NdbTransaction *trans,
bool force_release)
{
if (!force_release)
{
if (get_thd_ndb(current_thd)->query_state & NDB_QUERY_MULTI_READ_RANGE)
{
/* We are batching reads and have not consumed all fetched
rows yet, releasing operation records is unsafe
*/
return;
}
}
trans->releaseCompletedOperations();
}
/*
get table space info for SHOW CREATE TABLE
*/

View file

@ -534,6 +534,12 @@ class Ndb_cond_traverse_context
Ndb_rewrite_context *rewrite_stack;
};
typedef enum ndb_query_state_bits {
NDB_QUERY_NORMAL = 0,
NDB_QUERY_MULTI_READ_RANGE = 1
} NDB_QUERY_STATE_BITS;
/*
Place holder for ha_ndbcluster thread specific data
*/
@ -571,6 +577,7 @@ class Thd_ndb
int error;
uint32 options;
List<NDB_SHARE> changed_tables;
uint query_state;
HASH open_tables;
};
@ -833,6 +840,8 @@ private:
void no_uncommitted_rows_update(int);
void no_uncommitted_rows_reset(THD *);
void release_completed_operations(NdbTransaction*, bool);
/*
Condition pushdown
*/
@ -849,8 +858,8 @@ private:
friend int execute_commit(ha_ndbcluster*, NdbTransaction*);
friend int execute_no_commit_ignore_no_key(ha_ndbcluster*, NdbTransaction*);
friend int execute_no_commit(ha_ndbcluster*, NdbTransaction*);
friend int execute_no_commit_ie(ha_ndbcluster*, NdbTransaction*);
friend int execute_no_commit(ha_ndbcluster*, NdbTransaction*, bool);
friend int execute_no_commit_ie(ha_ndbcluster*, NdbTransaction*, bool);
NdbTransaction *m_active_trans;
NdbScanOperation *m_active_cursor;

View file

@ -3858,12 +3858,37 @@ err:
close_thread_tables(thd);
pthread_mutex_lock(&injector_mutex);
/* don't mess with the injector_ndb anymore from other threads */
int ndb_obj_cnt= 1; // g_ndb
ndb_obj_cnt+= injector_ndb == 0 ? 0 : 1;
ndb_obj_cnt+= schema_ndb == 0 ? 0 : 1;
ndb_obj_cnt+= ndbcluster_util_inited ? 1 : 0;
injector_thd= 0;
injector_ndb= 0;
schema_ndb= 0;
pthread_mutex_unlock(&injector_mutex);
thd->db= 0; // as not to try to free memory
if (!ndb_extra_logging)
sql_print_information("Stopping Cluster Binlog");
else
sql_print_information("Stopping Cluster Binlog: %u(%u)",
g_ndb_cluster_connection->get_active_ndb_objects(),
ndb_obj_cnt);
/**
* Add extra wait loop to make user "user" ndb-object go away...
* otherwise user thread can have ongoing SUB_DATA
*/
int sleep_cnt= 0;
while (sleep_cnt < 300 && g_ndb_cluster_connection->get_active_ndb_objects() > ndb_obj_cnt)
{
my_sleep(10000); // 10ms
sleep_cnt++;
}
if (ndb_extra_logging)
sql_print_information("Stopping Cluster Binlog: waited %ums %u(%u)",
10*sleep_cnt, g_ndb_cluster_connection->get_active_ndb_objects(),
ndb_obj_cnt);
if (apply_status_share)
{

View file

@ -344,6 +344,7 @@ static int ha_init_errors(void)
SETMSG(HA_ERR_TABLE_DEF_CHANGED, ER(ER_TABLE_DEF_CHANGED));
SETMSG(HA_ERR_FOREIGN_DUPLICATE_KEY, "FK constraint would lead to duplicate key");
SETMSG(HA_ERR_TABLE_NEEDS_UPGRADE, ER(ER_TABLE_NEEDS_UPGRADE));
SETMSG(HA_ERR_TABLE_READONLY, ER(ER_OPEN_AS_READONLY));
/* Register the error messages for use with my_error(). */
return my_error_register(errmsgs, HA_ERR_FIRST, HA_ERR_LAST);
@ -1422,6 +1423,34 @@ void handler::ha_statistic_increment(ulong SSV::*offset) const
statistic_increment(table->in_use->status_var.*offset, &LOCK_status);
}
bool handler::check_if_log_table_locking_is_allowed(uint sql_command,
ulong type, TABLE *table)
{
/*
Deny locking of the log tables, which is incompatible with
concurrent insert. Unless called from a logger THD:
general_log_thd or slow_log_thd.
*/
if (table->s->log_table &&
sql_command != SQLCOM_TRUNCATE &&
sql_command != SQLCOM_ALTER_TABLE &&
!(sql_command == SQLCOM_FLUSH &&
type & REFRESH_LOG) &&
(table->reginfo.lock_type >= TL_READ_NO_INSERT))
{
/*
The check >= TL_READ_NO_INSERT denies all write locks
plus the only read lock (TL_READ_NO_INSERT itself)
*/
table->reginfo.lock_type == TL_READ_NO_INSERT ?
my_error(ER_CANT_READ_LOCK_LOG_TABLE, MYF(0)) :
my_error(ER_CANT_WRITE_LOCK_LOG_TABLE, MYF(0));
return FALSE;
}
return TRUE;
}
/*
Open database-handler.
@ -2115,6 +2144,9 @@ void handler::print_error(int error, myf errflag)
case HA_ERR_TABLE_NEEDS_UPGRADE:
textno=ER_TABLE_NEEDS_UPGRADE;
break;
case HA_ERR_TABLE_READONLY:
textno= ER_OPEN_AS_READONLY;
break;
default:
{
/* The error was "unknown" to this function.

View file

@ -974,6 +974,8 @@ public:
{
return TRUE;
}
bool check_if_log_table_locking_is_allowed(uint sql_command,
ulong type, TABLE *table);
int ha_open(TABLE *table, const char *name, int mode, int test_if_locked);
void adjust_next_insert_id_after_explicit_value(ulonglong nr);
bool update_auto_increment();

View file

@ -1106,15 +1106,16 @@ void Log_to_csv_event_handler::
THD *log_thd, *curr= current_thd;
TABLE_LIST *table;
if (!logger.is_log_tables_initialized)
return; /* do nothing */
switch (log_table_type) {
case QUERY_LOG_GENERAL:
if (!logger.is_general_log_table_enabled())
return; /* do nothing */
log_thd= general_log_thd;
table= &general_log;
break;
case QUERY_LOG_SLOW:
if (!logger.is_slow_log_table_enabled())
return; /* do nothing */
log_thd= slow_log_thd;
table= &slow_log;
break;

View file

@ -497,6 +497,14 @@ public:
{}
void lock() { (void) pthread_mutex_lock(&LOCK_logger); }
void unlock() { (void) pthread_mutex_unlock(&LOCK_logger); }
bool is_general_log_table_enabled()
{
return table_log_handler && table_log_handler->general_log.table != 0;
}
bool is_slow_log_table_enabled()
{
return table_log_handler && table_log_handler->slow_log.table != 0;
}
/*
We want to initialize all log mutexes as soon as possible,
but we cannot do it in constructor, as safe_mutex relies on

View file

@ -2771,6 +2771,19 @@ static int init_common_variables(const char *conf_file_name, int argc,
else
sys_init_slave.value=my_strdup("",MYF(0));
/* check log options and issue warnings if needed */
if (opt_log && opt_logname && !(log_output_options & LOG_FILE) &&
!(log_output_options & LOG_NONE))
sql_print_warning("Although a path was specified for the "
"--log option, log tables are used. "
"To enable logging to file use the --log-output option.");
if (opt_slow_log && opt_slow_logname && !(log_output_options & LOG_FILE)
&& !(log_output_options & LOG_NONE))
sql_print_warning("Although a path was specified for the "
"--log-slow-queries option, log tables are used. "
"To enable logging to file use the --log-output option.");
if (!opt_logname)
opt_logname= make_default_log_name(buff, ".log");
sys_var_general_log_path.value= my_strdup(opt_logname, MYF(0));

View file

@ -5843,3 +5843,9 @@ ER_RBR_NOT_AVAILABLE
eng "The server was not built with row-based replication"
ER_NO_TRIGGERS_ON_SYSTEM_SCHEMA
eng "Triggers can not be created on system tables"
ER_CANT_ALTER_LOG_TABLE
eng "You can't alter a log table if logging is enabled"
ER_BAD_LOG_ENGINE
eng "One can use only CSV and MyISAM engines for the log tables"
ER_CANT_DROP_LOG_TABLE
eng "Cannot drop log table if log is enabled"

View file

@ -1841,7 +1841,6 @@ sp_use_new_db(THD *thd, LEX_STRING new_db, LEX_STRING *old_db,
bool no_access_check, bool *dbchangedp)
{
int ret;
static char empty_c_string[1]= {0}; /* used for not defined db */
DBUG_ENTER("sp_use_new_db");
DBUG_PRINT("enter", ("newdb: %s", new_db.str));

View file

@ -39,7 +39,7 @@ static bool table_def_inited= 0;
static int open_unireg_entry(THD *thd, TABLE *entry, TABLE_LIST *table_list,
const char *alias,
char *cache_key, uint cache_key_length,
MEM_ROOT *mem_root);
MEM_ROOT *mem_root, uint flags);
static void free_cache_entry(TABLE *entry);
static void mysql_rm_tmp_tables(void);
static bool open_new_frm(THD *thd, TABLE_SHARE *share, const char *alias,
@ -1763,7 +1763,7 @@ bool reopen_name_locked_table(THD* thd, TABLE_LIST* table_list)
if (open_unireg_entry(thd, table, table_list, table_name,
table->s->table_cache_key.str,
table->s->table_cache_key.length, thd->mem_root))
table->s->table_cache_key.length, thd->mem_root, 0))
{
intern_close_table(table);
/*
@ -1960,7 +1960,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
table= &tab;
VOID(pthread_mutex_lock(&LOCK_open));
if (!open_unireg_entry(thd, table, table_list, alias,
key, key_length, mem_root))
key, key_length, mem_root, 0))
{
DBUG_ASSERT(table_list->view != 0);
VOID(pthread_mutex_unlock(&LOCK_open));
@ -1997,17 +1997,17 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
table= (TABLE*) hash_next(&open_cache, (byte*) key, key_length,
&state))
{
if (table->s->version != refresh_version)
/*
Here we flush tables marked for flush. However we never flush log
tables here. They are flushed only on FLUSH LOGS.
*/
if (table->s->version != refresh_version && !table->s->log_table)
{
DBUG_PRINT("note",
("Found table '%s.%s' with different refresh version",
table_list->db, table_list->table_name));
/*
Don't close tables if we are working with a log table or were
asked not to close the table explicitly
*/
if (flags & MYSQL_LOCK_IGNORE_FLUSH || table->s->log_table)
if (flags & MYSQL_LOCK_IGNORE_FLUSH)
{
/* Force close at once after usage */
thd->version= table->s->version;
@ -2044,6 +2044,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
}
else
{
int error;
/* Free cache if too big */
while (open_cache.records > table_cache_size && unused_tables)
VOID(hash_delete(&open_cache,(byte*) unused_tables)); /* purecov: tested */
@ -2055,15 +2056,23 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
DBUG_RETURN(NULL);
}
if (open_unireg_entry(thd, table, table_list, alias, key, key_length,
mem_root))
error= open_unireg_entry(thd, table, table_list, alias, key, key_length,
mem_root, (flags & OPEN_VIEW_NO_PARSE));
if (error > 0)
{
my_free((gptr)table, MYF(0));
VOID(pthread_mutex_unlock(&LOCK_open));
DBUG_RETURN(NULL);
}
if (table_list->view)
if (table_list->view || error < 0)
{
/*
VIEW not really opened, only frm were read.
Set 1 as a flag here
*/
if (error < 0)
table_list->view= (st_lex*)1;
my_free((gptr)table, MYF(0));
VOID(pthread_mutex_unlock(&LOCK_open));
DBUG_RETURN(0); // VIEW
@ -2165,7 +2174,6 @@ static bool reopen_table(TABLE *table)
sql_print_error("Table %s had a open data handler in reopen_table",
table->alias);
#endif
table_list.db= table->s->db.str;
table_list.table_name= table->s->table_name.str;
table_list.table= table;
@ -2179,7 +2187,7 @@ static bool reopen_table(TABLE *table)
table->alias,
table->s->table_cache_key.str,
table->s->table_cache_key.length,
thd->mem_root))
thd->mem_root, 0))
goto end;
/* This list copies variables set by open_table */
@ -2346,7 +2354,11 @@ void close_old_data_files(THD *thd, TABLE *table, bool abort_locks,
for (; table ; table=table->next)
{
if (table->s->version != refresh_version)
/*
Reopen marked for flush. But close log tables. They are flushed only
explicitly on FLUSH LOGS
*/
if (table->s->version != refresh_version && !table->s->log_table)
{
found=1;
if (table->db_stat)
@ -2613,6 +2625,8 @@ void assign_new_table_id(TABLE_SHARE *share)
cache_key Key for share_cache
cache_key_length length of cache_key
mem_root temporary mem_root for parsing
flags the OPEN_VIEW_NO_PARSE flag to be passed to
openfrm()/open_new_frm()
NOTES
Extra argument for open is taken from thd->open_options
@ -2626,7 +2640,7 @@ void assign_new_table_id(TABLE_SHARE *share)
static int open_unireg_entry(THD *thd, TABLE *entry, TABLE_LIST *table_list,
const char *alias,
char *cache_key, uint cache_key_length,
MEM_ROOT *mem_root)
MEM_ROOT *mem_root, uint flags)
{
int error;
TABLE_SHARE *share;
@ -2647,14 +2661,15 @@ retry:
error= (int) open_new_frm(thd, share, alias,
(uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE |
HA_GET_INDEX | HA_TRY_READ_ONLY),
READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD,
READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD |
(flags & OPEN_VIEW_NO_PARSE),
thd->open_options, entry, table_list,
mem_root);
if (error)
goto err;
/* TODO: Don't free this */
release_table_share(share, RELEASE_NORMAL);
DBUG_RETURN(0);
DBUG_RETURN((flags & OPEN_VIEW_NO_PARSE)? -1 : 0);
}
while ((error= open_table_from_share(thd, share, alias,
@ -2707,7 +2722,6 @@ retry:
}
if (!entry->s || !entry->s->crashed)
goto err;
// Code below is for repairing a crashed file
if ((error= lock_table_name(thd, table_list, TRUE)))
{
@ -6339,7 +6353,8 @@ open_new_frm(THD *thd, TABLE_SHARE *share, const char *alias,
"BASE TABLE");
goto err;
}
if (mysql_make_view(thd, parser, table_desc))
if (mysql_make_view(thd, parser, table_desc,
(prgflag & OPEN_VIEW_NO_PARSE)))
goto err;
}
else

View file

@ -45,6 +45,7 @@
table name
*/
char internal_table_name[2]= "*";
char empty_c_string[1]= {0}; /* used for not defined db */
const char * const THD::DEFAULT_WHERE= "field list";

View file

@ -43,6 +43,7 @@ enum enum_mark_columns
{ MARK_COLUMNS_NONE, MARK_COLUMNS_READ, MARK_COLUMNS_WRITE};
extern char internal_table_name[2];
extern char empty_c_string[1];
extern const char **errmesg;
#define TC_LOG_PAGE_SIZE 8192
@ -1986,11 +1987,21 @@ public:
{
db.str=0;
}
/*
This constructor is used only for the case when we create a derived
table. A derived table has no name and doesn't belong to any database.
Later, if there was an alias specified for the table, it will be set
by add_table_to_list.
*/
inline Table_ident(SELECT_LEX_UNIT *s) : sel(s)
{
/* We must have a table name here as this is used with add_table_to_list */
db.str=0; table.str= internal_table_name; table.length=1;
db.str= empty_c_string; /* a subject to casedn_str */
db.length= 0;
table.str= internal_table_name;
table.length=1;
}
bool is_derived_table() const { return test(sel); }
inline void change_db(char *db_name)
{
db.str= db_name; db.length= (uint) strlen(db_name);

View file

@ -402,7 +402,7 @@ public:
friend class st_select_lex_unit;
friend bool mysql_new_select(struct st_lex *lex, bool move_down);
friend bool mysql_make_view(THD *thd, File_parser *parser,
TABLE_LIST *table);
TABLE_LIST *table, uint flags);
private:
void fast_exclude();
};

View file

@ -6380,12 +6380,14 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
if (!table)
DBUG_RETURN(0); // End of memory
alias_str= alias ? alias->str : table->table.str;
if (check_table_name(table->table.str,table->table.length))
if (check_table_name(table->table.str, table->table.length))
{
my_error(ER_WRONG_TABLE_NAME, MYF(0), table->table.str);
DBUG_RETURN(0);
}
if (table->db.str && check_db_name(table->db.str))
if (table->is_derived_table() == FALSE && table->db.str &&
check_db_name(table->db.str))
{
my_error(ER_WRONG_DB_NAME, MYF(0), table->db.str);
DBUG_RETURN(0);

View file

@ -4214,14 +4214,14 @@ greedy_search(JOIN *join,
double read_time= 0.0;
uint idx= join->const_tables; // index into 'join->best_ref'
uint best_idx;
uint rem_size; // cardinality of remaining_tables
uint size_remain; // cardinality of remaining_tables
POSITION best_pos;
JOIN_TAB *best_table; // the next plan node to be added to the curr QEP
DBUG_ENTER("greedy_search");
/* number of tables that remain to be optimized */
rem_size= my_count_bits(remaining_tables);
size_remain= my_count_bits(remaining_tables);
do {
/* Find the extension of the current QEP with the lowest cost */
@ -4229,7 +4229,7 @@ greedy_search(JOIN *join,
best_extension_by_limited_search(join, remaining_tables, idx, record_count,
read_time, search_depth, prune_level);
if (rem_size <= search_depth)
if (size_remain <= search_depth)
{
/*
'join->best_positions' contains a complete optimal extension of the
@ -4265,7 +4265,7 @@ greedy_search(JOIN *join,
read_time+= join->positions[idx].read_time;
remaining_tables&= ~(best_table->table->map);
--rem_size;
--size_remain;
++idx;
DBUG_EXECUTE("opt", print_plan(join, join->tables,
@ -8599,12 +8599,14 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
&bitmaps, bitmap_buffer_size(field_count)*2,
NullS))
{
if (temp_pool_slot != MY_BIT_NONE)
bitmap_lock_clear_bit(&temp_pool, temp_pool_slot);
DBUG_RETURN(NULL); /* purecov: inspected */
}
/* Copy_field belongs to TMP_TABLE_PARAM, allocate it in THD mem_root */
if (!(param->copy_field= copy= new (thd->mem_root) Copy_field[field_count]))
{
if (temp_pool_slot != MY_BIT_NONE)
bitmap_lock_clear_bit(&temp_pool, temp_pool_slot);
free_root(&own_root, MYF(0)); /* purecov: inspected */
DBUG_RETURN(NULL); /* purecov: inspected */
@ -9132,6 +9134,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
err:
thd->mem_root= mem_root_save;
free_tmp_table(thd,table); /* purecov: inspected */
if (temp_pool_slot != MY_BIT_NONE)
bitmap_lock_clear_bit(&temp_pool, temp_pool_slot);
DBUG_RETURN(NULL); /* purecov: inspected */
}
@ -9420,6 +9423,7 @@ free_tmp_table(THD *thd, TABLE *entry)
(*ptr)->free();
free_io_cache(entry);
if (entry->temp_pool_slot != MY_BIT_NONE)
bitmap_lock_clear_bit(&temp_pool, entry->temp_pool_slot);
free_root(&own_root, MYF(0)); /* the table is allocated in its own root */

View file

@ -1537,6 +1537,18 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
table->db_type= NULL;
if ((share= get_cached_table_share(table->db, table->table_name)))
table->db_type= share->db_type;
/* Disable drop of enabled log tables */
if (share && share->log_table &&
((!my_strcasecmp(system_charset_info, table->table_name,
"general_log") && opt_log &&
logger.is_general_log_table_enabled()) ||
(!my_strcasecmp(system_charset_info, table->table_name, "slow_log")
&& opt_slow_log && logger.is_slow_log_table_enabled())))
{
my_error(ER_CANT_DROP_LOG_TABLE, MYF(0));
DBUG_RETURN(1);
}
}
if (lock_table_names(thd, tables))
@ -5003,6 +5015,43 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
LINT_INIT(index_add_buffer);
LINT_INIT(index_drop_buffer);
if (table_list && table_list->db &&
!my_strcasecmp(system_charset_info, table_list->db, "mysql") &&
table_list->table_name)
{
enum enum_table_kind { NOT_LOG_TABLE= 1, GENERAL_LOG, SLOW_LOG }
table_kind= NOT_LOG_TABLE;
if (!my_strcasecmp(system_charset_info, table_list->table_name,
"general_log"))
table_kind= GENERAL_LOG;
else
if (!my_strcasecmp(system_charset_info, table_list->table_name,
"slow_log"))
table_kind= SLOW_LOG;
/* Disable alter of enabled log tables */
if ((table_kind == GENERAL_LOG && opt_log &&
logger.is_general_log_table_enabled()) ||
(table_kind == SLOW_LOG && opt_slow_log &&
logger.is_slow_log_table_enabled()))
{
my_error(ER_CANT_ALTER_LOG_TABLE, MYF(0));
DBUG_RETURN(TRUE);
}
/* Disable alter of log tables to unsupported engine */
if ((table_kind == GENERAL_LOG || table_kind == SLOW_LOG) &&
(lex_create_info->used_fields & HA_CREATE_USED_ENGINE) &&
(!lex_create_info->db_type || /* unknown engine */
!(lex_create_info->db_type->db_type == DB_TYPE_MYISAM ||
lex_create_info->db_type->db_type == DB_TYPE_CSV_DB)))
{
my_error(ER_BAD_LOG_ENGINE, MYF(0));
DBUG_RETURN(TRUE);
}
}
thd->proc_info="init";
if (!(create_info= copy_create_info(lex_create_info)))
{

View file

@ -183,7 +183,7 @@ fill_defined_view_parts (THD *thd, TABLE_LIST *view)
TABLE_LIST decoy;
memcpy (&decoy, view, sizeof (TABLE_LIST));
if (!open_table(thd, &decoy, thd->mem_root, &not_used, 0) &&
if (!open_table(thd, &decoy, thd->mem_root, &not_used, OPEN_VIEW_NO_PARSE) &&
!decoy.view)
{
return TRUE;
@ -817,13 +817,14 @@ loop_out:
thd Thread handler
parser parser object
table TABLE_LIST structure for filling
flags flags
RETURN
0 ok
1 error
*/
bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table)
bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
uint flags)
{
SELECT_LEX *end, *view_select;
LEX *old_lex, *lex;
@ -914,6 +915,10 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table)
table->db, table->table_name);
get_default_definer(thd, &table->definer);
}
if (flags & OPEN_VIEW_NO_PARSE)
{
DBUG_RETURN(FALSE);
}
/*
Save VIEW parameters, which will be wiped out by derived table

View file

@ -19,7 +19,8 @@
bool mysql_create_view(THD *thd,
enum_view_create_mode mode);
bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table);
bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
uint flags);
bool mysql_drop_view(THD *thd, TABLE_LIST *view, enum_drop_mode drop_mode);

View file

@ -127,7 +127,7 @@ typedef long long longlong;
#else
#include <my_global.h>
#include <my_sys.h>
#include <m_string.h> // To get strmov()
#include <m_string.h> /* To get strmov() */
#endif
#include <mysql.h>
#include <ctype.h>
@ -138,7 +138,6 @@ static pthread_mutex_t LOCK_hostname;
/* These must be right or mysqld will not find the symbol! */
extern "C" {
my_bool metaphon_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
void metaphon_deinit(UDF_INIT *initid);
char *metaphon(UDF_INIT *initid, UDF_ARGS *args, char *result,
@ -159,7 +158,6 @@ void avgcost_reset( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error
void avgcost_clear( UDF_INIT* initid, char* is_null, char *error );
void avgcost_add( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error );
double avgcost( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char *error );
}
/*************************************************************************
@ -221,7 +219,7 @@ my_bool metaphon_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
****************************************************************************/
void metaphon_deinit(UDF_INIT *initid)
void metaphon_deinit(UDF_INIT *initid __attribute__((unused)))
{
}
@ -267,23 +265,25 @@ static char codes[26] = {
#define NOGHTOF(x) (codes[(x) - 'A'] & 16) /* BDH */
char *metaphon(UDF_INIT *initid, UDF_ARGS *args, char *result,
unsigned long *length, char *is_null, char *error)
char *metaphon(UDF_INIT *initid __attribute__((unused)),
UDF_ARGS *args, char *result, unsigned long *length,
char *is_null, char *error __attribute__((unused)))
{
const char *word=args->args[0];
if (!word) // Null argument
const char *w_end;
char *org_result;
char *n, *n_start, *n_end; /* pointers to string */
char *metaph_end; /* pointers to end of metaph */
char ntrans[32]; /* word with uppercase letters */
int KSflag; /* state flag for X to KS */
if (!word) /* Null argument */
{
*is_null=1;
return 0;
}
const char *w_end=word+args->lengths[0];
char *org_result=result;
char *n, *n_start, *n_end; /* pointers to string */
char *metaph, *metaph_end; /* pointers to metaph */
char ntrans[32]; /* word with uppercase letters */
char newm[8]; /* new metaph for comparison */
int KSflag; /* state flag for X to KS */
w_end=word+args->lengths[0];
org_result=result;
/*--------------------------------------------------------
* Copy word to internal buffer, dropping non-alphabetic
@ -519,6 +519,8 @@ char *metaphon(UDF_INIT *initid, UDF_ARGS *args, char *result,
my_bool myfunc_double_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{
uint i;
if (!args->arg_count)
{
strcpy(message,"myfunc_double must have at least one argument");
@ -528,27 +530,28 @@ my_bool myfunc_double_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
** As this function wants to have everything as strings, force all arguments
** to strings.
*/
for (uint i=0 ; i < args->arg_count; i++)
for (i=0 ; i < args->arg_count; i++)
args->arg_type[i]=STRING_RESULT;
initid->maybe_null=1; // The result may be null
initid->decimals=2; // We want 2 decimals in the result
initid->max_length=6; // 3 digits + . + 2 decimals
initid->maybe_null=1; /* The result may be null */
initid->decimals=2; /* We want 2 decimals in the result */
initid->max_length=6; /* 3 digits + . + 2 decimals */
return 0;
}
double myfunc_double(UDF_INIT *initid, UDF_ARGS *args, char *is_null,
char *error)
double myfunc_double(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args,
char *is_null, char *error __attribute__((unused)))
{
unsigned long val = 0;
unsigned long v = 0;
uint i, j;
for (uint i = 0; i < args->arg_count; i++)
for (i = 0; i < args->arg_count; i++)
{
if (args->args[i] == NULL)
continue;
val += args->lengths[i];
for (uint j=args->lengths[i] ; j-- > 0 ;)
for (j=args->lengths[i] ; j-- > 0 ;)
v += args->args[i][j];
}
if (val)
@ -575,22 +578,25 @@ double myfunc_double(UDF_INIT *initid, UDF_ARGS *args, char *is_null,
/* This function returns the sum of all arguments */
longlong myfunc_int(UDF_INIT *initid, UDF_ARGS *args, char *is_null,
char *error)
longlong myfunc_int(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args,
char *is_null __attribute__((unused)),
char *error __attribute__((unused)))
{
longlong val = 0;
for (uint i = 0; i < args->arg_count; i++)
uint i;
for (i = 0; i < args->arg_count; i++)
{
if (args->args[i] == NULL)
continue;
switch (args->arg_type[i]) {
case STRING_RESULT: // Add string lengths
case STRING_RESULT: /* Add string lengths */
val += args->lengths[i];
break;
case INT_RESULT: // Add numbers
case INT_RESULT: /* Add numbers */
val += *((longlong*) args->args[i]);
break;
case REAL_RESULT: // Add numers as longlong
case REAL_RESULT: /* Add numers as longlong */
val += (longlong) *((double*) args->args[i]);
break;
default:
@ -604,7 +610,9 @@ longlong myfunc_int(UDF_INIT *initid, UDF_ARGS *args, char *is_null,
At least one of _init/_deinit is needed unless the server is started
with --allow_suspicious_udfs.
*/
my_bool myfunc_int_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
my_bool myfunc_int_init(UDF_INIT *initid __attribute__((unused)),
UDF_ARGS *args __attribute__((unused)),
char *message __attribute__((unused)))
{
return 0;
}
@ -622,7 +630,7 @@ my_bool sequence_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
return 1;
}
if (args->arg_count)
args->arg_type[0]= INT_RESULT; // Force argument to int
args->arg_type[0]= INT_RESULT; /* Force argument to int */
if (!(initid->ptr=(char*) malloc(sizeof(longlong))))
{
@ -646,8 +654,9 @@ void sequence_deinit(UDF_INIT *initid)
free(initid->ptr);
}
longlong sequence(UDF_INIT *initid, UDF_ARGS *args, char *is_null,
char *error)
longlong sequence(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args,
char *is_null __attribute__((unused)),
char *error __attribute__((unused)))
{
ulonglong val=0;
if (args->arg_count)
@ -670,7 +679,6 @@ longlong sequence(UDF_INIT *initid, UDF_ARGS *args, char *is_null,
#include <arpa/inet.h>
#include <netdb.h>
extern "C" {
my_bool lookup_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
void lookup_deinit(UDF_INIT *initid);
char *lookup(UDF_INIT *initid, UDF_ARGS *args, char *result,
@ -679,7 +687,6 @@ my_bool reverse_lookup_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
void reverse_lookup_deinit(UDF_INIT *initid);
char *reverse_lookup(UDF_INIT *initid, UDF_ARGS *args, char *result,
unsigned long *length, char *null_value, char *error);
}
/****************************************************************************
@ -705,20 +712,26 @@ my_bool lookup_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
return 0;
}
void lookup_deinit(UDF_INIT *initid)
void lookup_deinit(UDF_INIT *initid __attribute__((unused)))
{
#if !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_SOLARIS_STYLE_GETHOST)
(void) pthread_mutex_destroy(&LOCK_hostname);
#endif
}
char *lookup(UDF_INIT *initid, UDF_ARGS *args, char *result,
unsigned long *res_length, char *null_value, char *error)
char *lookup(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args,
char *result, unsigned long *res_length, char *null_value,
char *error __attribute__((unused)))
{
uint length;
char name_buff[256];
struct hostent *hostent;
#if defined(HAVE_GETHOSTBYADDR_R) && defined(HAVE_SOLARIS_STYLE_GETHOST)
int tmp_errno;
char name_buff[256],hostname_buff[2048];
struct hostent tmp_hostent,*hostent;
char hostname_buff[2048];
struct hostent tmp_hostent;
#endif
struct in_addr in;
if (!args->args[0] || !(length=args->lengths[0]))
{
@ -746,7 +759,6 @@ char *lookup(UDF_INIT *initid, UDF_ARGS *args, char *result,
}
VOID(pthread_mutex_unlock(&LOCK_hostname));
#endif
struct in_addr in;
memcpy_fixed((char*) &in,(char*) *hostent->h_addr_list, sizeof(in.s_addr));
*res_length= (ulong) (strmov(result, inet_ntoa(in)) - result);
return result;
@ -780,18 +792,23 @@ my_bool reverse_lookup_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
return 0;
}
void reverse_lookup_deinit(UDF_INIT *initid)
void reverse_lookup_deinit(UDF_INIT *initid __attribute__((unused)))
{
#if !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_SOLARIS_STYLE_GETHOST)
(void) pthread_mutex_destroy(&LOCK_hostname);
#endif
}
char *reverse_lookup(UDF_INIT *initid, UDF_ARGS *args, char *result,
unsigned long *res_length, char *null_value, char *error)
char *reverse_lookup(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args,
char *result, unsigned long *res_length,
char *null_value, char *error __attribute__((unused)))
{
#if defined(HAVE_GETHOSTBYADDR_R) && defined(HAVE_SOLARIS_STYLE_GETHOST)
char name_buff[256];
struct hostent tmp_hostent;
#endif
struct hostent *hp;
unsigned long taddr;
uint length;
if (args->arg_count == 4)
@ -808,8 +825,8 @@ char *reverse_lookup(UDF_INIT *initid, UDF_ARGS *args, char *result,
(int) *((longlong*) args->args[3]));
}
else
{ // string argument
if (!args->args[0]) // Return NULL for NULL values
{ /* string argument */
if (!args->args[0]) /* Return NULL for NULL values */
{
*null_value=1;
return 0;
@ -821,13 +838,12 @@ char *reverse_lookup(UDF_INIT *initid, UDF_ARGS *args, char *result,
result[length]=0;
}
unsigned long taddr = inet_addr(result);
taddr = inet_addr(result);
if (taddr == (unsigned long) -1L)
{
*null_value=1;
return 0;
}
struct hostent *hp;
#if defined(HAVE_GETHOSTBYADDR_R) && defined(HAVE_SOLARIS_STYLE_GETHOST)
int tmp_errno;
if (!(hp=gethostbyaddr_r((char*) &taddr,sizeof(taddr), AF_INET,
@ -902,11 +918,15 @@ avgcost_init( UDF_INIT* initid, UDF_ARGS* args, char* message )
/*args->arg_type[0] = REAL_RESULT;
args->arg_type[1] = REAL_RESULT;*/
initid->maybe_null = 0; // The result may be null
initid->decimals = 4; // We want 4 decimals in the result
initid->max_length = 20; // 6 digits + . + 10 decimals
initid->maybe_null = 0; /* The result may be null */
initid->decimals = 4; /* We want 4 decimals in the result */
initid->max_length = 20; /* 6 digits + . + 10 decimals */
data = new struct avgcost_data;
if (!(data = (struct avgcost_data*) malloc(sizeof(struct avgcost_data))))
{
strmov(message,"Couldn't allocate memory");
return 1;
}
data->totalquantity = 0;
data->totalprice = 0.0;
@ -918,7 +938,7 @@ avgcost_init( UDF_INIT* initid, UDF_ARGS* args, char* message )
void
avgcost_deinit( UDF_INIT* initid )
{
delete initid->ptr;
free(initid->ptr);
}
@ -933,7 +953,8 @@ avgcost_reset(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* message)
/* This is needed to get things to work in MySQL 4.1.1 and above */
void
avgcost_clear(UDF_INIT* initid, char* is_null, char* message)
avgcost_clear(UDF_INIT* initid, char* is_null __attribute__((unused)),
char* message __attribute__((unused)))
{
struct avgcost_data* data = (struct avgcost_data*)initid->ptr;
data->totalprice= 0.0;
@ -943,7 +964,9 @@ avgcost_clear(UDF_INIT* initid, char* is_null, char* message)
void
avgcost_add(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* message)
avgcost_add(UDF_INIT* initid, UDF_ARGS* args,
char* is_null __attribute__((unused)),
char* message __attribute__((unused)))
{
if (args->args[0] && args->args[1])
{
@ -963,7 +986,7 @@ avgcost_add(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* message)
if ( ((quantity < 0) && (newquantity < 0))
|| ((quantity > 0) && (newquantity > 0)) )
{
data->totalprice = price * double(newquantity);
data->totalprice = price * (double)newquantity;
}
/*
** sub q if totalq > 0
@ -971,15 +994,15 @@ avgcost_add(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* message)
*/
else
{
price = data->totalprice / double(data->totalquantity);
data->totalprice = price * double(newquantity);
price = data->totalprice / (double)data->totalquantity;
data->totalprice = price * (double)newquantity;
}
data->totalquantity = newquantity;
}
else
{
data->totalquantity += quantity;
data->totalprice += price * double(quantity);
data->totalprice += price * (double)quantity;
}
if (data->totalquantity == 0)
@ -989,7 +1012,8 @@ avgcost_add(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* message)
double
avgcost( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error )
avgcost( UDF_INIT* initid, UDF_ARGS* args __attribute__((unused)),
char* is_null, char* error __attribute__((unused)))
{
struct avgcost_data* data = (struct avgcost_data*)initid->ptr;
if (!data->count || !data->totalquantity)
@ -999,16 +1023,14 @@ avgcost( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error )
}
*is_null = 0;
return data->totalprice/double(data->totalquantity);
return data->totalprice/(double)data->totalquantity;
}
extern "C" {
my_bool myfunc_argument_name_init(UDF_INIT *initid, UDF_ARGS *args,
char *message);
char *myfunc_argument_name(UDF_INIT *initid, UDF_ARGS *args, char *result,
unsigned long *length, char *null_value,
char *error);
}
my_bool myfunc_argument_name_init(UDF_INIT *initid, UDF_ARGS *args,
char *message)
@ -1024,16 +1046,17 @@ my_bool myfunc_argument_name_init(UDF_INIT *initid, UDF_ARGS *args,
return 0;
}
char *myfunc_argument_name(UDF_INIT *initid, UDF_ARGS *args, char *result,
char *myfunc_argument_name(UDF_INIT *initid __attribute__((unused)),
UDF_ARGS *args, char *result,
unsigned long *length, char *null_value,
char *error)
char *error __attribute__((unused)))
{
if (!args->attributes[0])
{
null_value= 0;
return 0;
}
(*length)--; // space for ending \0 (for debugging purposes)
(*length)--; /* space for ending \0 (for debugging purposes) */
if (*length > args->attribute_lengths[0])
*length= args->attribute_lengths[0];
memcpy(result, args->attributes[0], *length);

View file

@ -151,7 +151,8 @@
#define READ_SCREENS 1024 /* Read screens, info and helpfile */
#define DELAYED_OPEN 4096 /* Open table later */
#define OPEN_VIEW 8192 /* Allow open on view */
#define OPEN_VIEW_NO_PARSE 16384 /* Open frm only if it's a view,
but do not parse view itself */
#define SC_INFO_LENGTH 4 /* Form format constant */
#define TE_INFO_LENGTH 3
#define MTYP_NOEMPTY_BIT 128

View file

@ -817,27 +817,9 @@ bool ha_tina::check_if_locking_is_allowed(uint sql_command,
uint count,
bool called_by_logger_thread)
{
/*
Deny locking of the log tables, which is incompatible with
concurrent insert. Unless called from a logger THD:
general_log_thd or slow_log_thd.
*/
if (table->s->log_table &&
sql_command != SQLCOM_TRUNCATE &&
!(sql_command == SQLCOM_FLUSH &&
type & REFRESH_LOG) &&
!called_by_logger_thread &&
(table->reginfo.lock_type >= TL_READ_NO_INSERT))
{
/*
The check >= TL_READ_NO_INSERT denies all write locks
plus the only read lock (TL_READ_NO_INSERT itself)
*/
table->reginfo.lock_type == TL_READ_NO_INSERT ?
my_error(ER_CANT_READ_LOCK_LOG_TABLE, MYF(0)) :
my_error(ER_CANT_WRITE_LOCK_LOG_TABLE, MYF(0));
return FALSE;
}
if (!called_by_logger_thread)
return check_if_log_table_locking_is_allowed(sql_command, type, table);
return TRUE;
}

View file

@ -366,6 +366,11 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
pthread_mutex_unlock(&share->intern_lock);
#endif
break;
case HA_EXTRA_MARK_AS_LOG_TABLE:
pthread_mutex_lock(&share->intern_lock);
share->is_log_table= TRUE;
pthread_mutex_unlock(&share->intern_lock);
break;
case HA_EXTRA_KEY_CACHE:
case HA_EXTRA_NO_KEY_CACHE:
default:

View file

@ -489,6 +489,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
share->data_file_type = DYNAMIC_RECORD;
my_afree((gptr) disk_cache);
mi_setup_functions(share);
share->is_log_table= FALSE;
#ifdef THREAD
thr_lock_init(&share->lock);
VOID(pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST));

View file

@ -163,6 +163,18 @@ int mi_write(MI_INFO *info, byte *record)
(*info->invalidator)(info->filename);
info->invalidator=0;
}
/*
Update status of the table. We need to do so after each row write
for the log tables, as we want the new row to become visible to
other threads as soon as possible. We lock mutex here to follow
pthread memory visibility rules.
*/
pthread_mutex_lock(&share->intern_lock);
if (share->is_log_table)
mi_update_status((void*) info);
pthread_mutex_unlock(&share->intern_lock);
allow_break(); /* Allow SIGHUP & SIGINT */
DBUG_RETURN(0);

View file

@ -201,6 +201,9 @@ typedef struct st_mi_isam_share { /* Shared between opens */
uint blocksize; /* blocksize of keyfile */
myf write_flag;
enum data_file_type data_file_type;
/* Below flag is needed to make log tables work with concurrent insert */
my_bool is_log_table;
my_bool changed, /* If changed since lock */
global_changed, /* If changed since open */
not_flushed,

View file

@ -140,6 +140,7 @@ class NdbTransaction
friend class NdbIndexOperation;
friend class NdbIndexScanOperation;
friend class NdbBlob;
friend class ha_ndbcluster;
#endif
public:

View file

@ -114,6 +114,7 @@ public:
void init_get_next_node(Ndb_cluster_connection_node_iter &iter);
unsigned int get_next_node(Ndb_cluster_connection_node_iter &iter);
unsigned get_active_ndb_objects() const;
#endif
private:

View file

@ -742,9 +742,12 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3])
const Uint32 oid = sdata->senderData;
NdbEventOperationImpl *op= (NdbEventOperationImpl*)int2void(oid);
if (op->m_magic_number != NDB_EVENT_OP_MAGIC_NUMBER)
if (unlikely(op == 0 || op->m_magic_number != NDB_EVENT_OP_MAGIC_NUMBER))
{
g_eventLogger.error("dropped GSN_SUB_TABLE_DATA due to wrong magic "
"number");
return ;
}
// Accumulate DIC_TAB_INFO for TE_ALTER events
if (sdata->operation == NdbDictionary::Event::_TE_ALTER &&

View file

@ -1265,6 +1265,7 @@ TransporterFacade::get_an_alive_node()
}
TransporterFacade::ThreadData::ThreadData(Uint32 size){
m_use_cnt = 0;
m_firstFree = END_OF_LIST;
expand(size);
}
@ -1302,6 +1303,7 @@ TransporterFacade::ThreadData::open(void* objRef,
nextFree = m_firstFree;
}
m_use_cnt++;
m_firstFree = m_statusNext[nextFree];
Object_Execute oe = { objRef , fun };
@ -1318,6 +1320,8 @@ TransporterFacade::ThreadData::close(int number){
number= numberToIndex(number);
assert(getInUse(number));
m_statusNext[number] = m_firstFree;
assert(m_use_cnt);
m_use_cnt--;
m_firstFree = number;
Object_Execute oe = { 0, 0 };
m_objectExecute[number] = oe;
@ -1325,6 +1329,12 @@ TransporterFacade::ThreadData::close(int number){
return 0;
}
Uint32
TransporterFacade::get_active_ndb_objects() const
{
return m_threads.m_use_cnt;
}
PollGuard::PollGuard(TransporterFacade *tp, NdbWaiter *aWaiter,
Uint32 block_no)
{

View file

@ -68,6 +68,7 @@ public:
// Close this block number
int close(BlockNumber blockNumber, Uint64 trans_id);
Uint32 get_active_ndb_objects() const;
// Only sends to nodes which are alive
int sendSignal(NdbApiSignal * signal, NodeId nodeId);
@ -240,6 +241,7 @@ private:
NodeStatusFunction m_statusFunction;
};
Uint32 m_use_cnt;
Uint32 m_firstFree;
Vector<Uint32> m_statusNext;
Vector<Object_Execute> m_objectExecute;

View file

@ -599,5 +599,10 @@ Ndb_cluster_connection::get_next_node(Ndb_cluster_connection_node_iter &iter)
return m_impl.get_next_node(iter);
}
unsigned
Ndb_cluster_connection::get_active_ndb_objects() const
{
return m_impl.m_transporter_facade->get_active_ndb_objects();
}
template class Vector<Ndb_cluster_connection_impl::Node>;

View file

@ -26,8 +26,7 @@
*/
#include "my_base.h" /* Defines EOVERFLOW on Windows */
#include "my_global.h" /* Includes errno.h */
#include "my_base.h" /* Includes errno.h + EOVERFLOW */
#include "m_ctype.h"
#define MAX_DBL_EXP 308

View file

@ -552,15 +552,18 @@ fi
%doc %attr(644, root, root) %{_infodir}/mysql.info*
%doc %attr(644, root, man) %{_mandir}/man1/myisam_ftdump.1*
%doc %attr(644, root, man) %{_mandir}/man1/myisamchk.1*
%doc %attr(644, root, man) %{_mandir}/man1/myisamlog.1*
%doc %attr(644, root, man) %{_mandir}/man1/myisampack.1*
%doc %attr(644, root, man) %{_mandir}/man1/mysqld.1*
%doc %attr(644, root, man) %{_mandir}/man1/mysql_explain_log.1*
%doc %attr(644, root, man) %{_mandir}/man8/mysqld.8*
%doc %attr(644, root, man) %{_mandir}/man1/mysqld_multi.1*
%doc %attr(644, root, man) %{_mandir}/man1/mysqld_safe.1*
%doc %attr(644, root, man) %{_mandir}/man1/mysql_fix_privilege_tables.1*
%doc %attr(644, root, man) %{_mandir}/man1/mysql_upgrade.1*
%doc %attr(644, root, man) %{_mandir}/man1/mysqlhotcopy.1*
%doc %attr(644, root, man) %{_mandir}/man1/mysqlman.1*
%doc %attr(644, root, man) %{_mandir}/man1/mysqlmanager.1*
%doc %attr(644, root, man) %{_mandir}/man1/mysql.server.1*
%doc %attr(644, root, man) %{_mandir}/man1/mysql_zap.1*
@ -646,7 +649,6 @@ fi
%files ndb-management
%defattr(-,root,root,0755)
%attr(755, root, root) %{_sbindir}/ndb_mgmd
%attr(755, root, root) %{_bindir}/ndb_mgm
%files ndb-tools
%defattr(-,root,root,0755)

View file

@ -15227,6 +15227,51 @@ static void test_bug20152()
DIE_UNLESS(0==1);
}
}
/*
Bug#21206: memory corruption when too many cursors are opened at once
Memory corruption happens when more than 1024 cursors are open
simultaneously.
*/
static void test_bug21206()
{
const size_t cursor_count= 1025;
const char *create_table[]=
{
"DROP TABLE IF EXISTS t1",
"CREATE TABLE t1 (i INT)",
"INSERT INTO t1 VALUES (1), (2), (3)"
};
const char *query= "SELECT * FROM t1";
Stmt_fetch *fetch_array=
(Stmt_fetch*) calloc(cursor_count, sizeof(Stmt_fetch));
Stmt_fetch *fetch;
DBUG_ENTER("test_bug21206");
myheader("test_bug21206");
fill_tables(create_table, sizeof(create_table) / sizeof(*create_table));
for (fetch= fetch_array; fetch < fetch_array + cursor_count; ++fetch)
{
/* Init will exit(1) in case of error */
stmt_fetch_init(fetch, fetch - fetch_array, query);
}
for (fetch= fetch_array; fetch < fetch_array + cursor_count; ++fetch)
stmt_fetch_close(fetch);
free(fetch_array);
DBUG_VOID_RETURN;
}
/*
Read and parse arguments and MySQL options from my.cnf
*/
@ -15490,7 +15535,9 @@ static struct my_tests_st my_tests[]= {
{ "test_bug14845", test_bug14845 },
{ "test_opt_reconnect", test_opt_reconnect },
{ "test_bug15510", test_bug15510},
#ifndef EMBEDDED_LIBRARY
{ "test_bug12744", test_bug12744 },
#endif
{ "test_bug16143", test_bug16143 },
{ "test_bug16144", test_bug16144 },
{ "test_bug15613", test_bug15613 },
@ -15499,6 +15546,7 @@ static struct my_tests_st my_tests[]= {
{ "test_bug17667", test_bug17667 },
{ "test_mysql_insert_id", test_mysql_insert_id },
{ "test_bug19671", test_bug19671},
{ "test_bug21206", test_bug21206},
{ 0, 0 }
};