mirror of
https://github.com/MariaDB/server.git
synced 2026-04-30 12:15:32 +02:00
Merge tulin@bk-internal.mysql.com:/home/bk/mysql-5.0
into dl145b.mysql.com:/home/ndbdev/tomas/mysql-5.1 configure.in: Auto merged include/my_global.h: Auto merged sql/handler.cc: Auto merged sql/item.cc: Auto merged sql/log.cc: Auto merged sql/opt_range.cc: Auto merged sql/set_var.cc: Auto merged sql/set_var.h: Auto merged sql/sql_base.cc: Auto merged sql/sql_class.h: Auto merged sql/sql_parse.cc: Auto merged sql/examples/ha_tina.cc: Auto merged sql/sql_select.cc: Auto merged sql/sql_select.h: Auto merged sql/sql_show.cc: Auto merged sql/sql_yacc.yy: Auto merged storage/ndb/include/kernel/signaldata/BackupImpl.hpp: Auto merged storage/ndb/include/kernel/signaldata/BackupSignalData.hpp: Auto merged storage/ndb/include/kernel/signaldata/NFCompleteRep.hpp: Auto merged storage/ndb/include/kernel/signaldata/NodeFailRep.hpp: Auto merged storage/ndb/src/kernel/blocks/backup/Backup.cpp: Auto merged storage/ndb/src/kernel/blocks/backup/Backup.hpp: Auto merged storage/ndb/src/kernel/main.cpp: Auto merged storage/ndb/src/mgmsrv/MgmtSrvr.cpp: Auto merged storage/ndb/src/mgmsrv/MgmtSrvr.hpp: Auto merged storage/ndb/src/ndbapi/Makefile.am: Auto merged storage/ndb/src/ndbapi/NdbTransaction.cpp: Auto merged storage/ndb/test/src/NdbBackup.cpp: Auto merged
This commit is contained in:
commit
36aeee3682
76 changed files with 1901 additions and 442 deletions
0
BitKeeper/etc/RESYNC_TREE
Normal file
0
BitKeeper/etc/RESYNC_TREE
Normal file
|
|
@ -37,8 +37,9 @@ static char *add_load_option(char *ptr,const char *object,
|
|||
const char *statement);
|
||||
|
||||
static my_bool verbose=0,lock_tables=0,ignore_errors=0,opt_delete=0,
|
||||
replace=0,silent=0,ignore=0,opt_compress=0,opt_local_file=0,
|
||||
replace=0,silent=0,ignore=0,opt_compress=0,
|
||||
opt_low_priority= 0, tty_password= 0;
|
||||
static uint opt_local_file=0;
|
||||
static MYSQL mysql_connection;
|
||||
static char *opt_password=0, *current_user=0,
|
||||
*current_host=0, *current_db=0, *fields_terminated=0,
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ public:
|
|||
|
||||
|
||||
// no gas on these systems ?, disable for now
|
||||
#if defined(__sun__) || defined (__QNX__)
|
||||
#if defined(__sun__) || defined (__QNX__) || defined (__APPLE__)
|
||||
#define TAOCRYPT_DISABLE_X86ASM
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,8 @@
|
|||
|
||||
|
||||
|
||||
#if !defined(yaSSL_NEW_HPP) && defined(__GNUC__) && !defined(__ICC)
|
||||
#if !defined(yaSSL_NEW_HPP) && defined(__GNUC__)
|
||||
#if !(defined(__ICC) || defined(__INTEL_COMPILER))
|
||||
|
||||
#define yaSSL_NEW_HPP
|
||||
|
||||
|
|
@ -46,5 +47,6 @@ static int __cxa_pure_virtual()
|
|||
} // extern "C"
|
||||
|
||||
#endif // __GNUC__ > 2
|
||||
#endif // ! _ICC
|
||||
#endif // yaSSL_NEW_HPP && __GNUC__
|
||||
|
||||
|
|
|
|||
|
|
@ -61,9 +61,10 @@ typedef unsigned int word32;
|
|||
|
||||
// compilers we've found 64-bit multiply insructions for
|
||||
#if defined(__GNUC__) || defined(_MSC_VER) || defined(__DECCXX)
|
||||
#if !(defined(__ICC) || defined(__INTEL_COMPILER))
|
||||
#define HAVE_64_MULTIPLY
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_64_MULTIPLY) && (defined(__alpha__) || defined(__ia64__) \
|
||||
|| defined(_ARCH_PPC64) || defined(__mips64) || defined(__x86_64__))
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
drop table if exists t1,t2;
|
||||
show tables;
|
||||
Tables_in_mysql
|
||||
columns_priv
|
||||
|
|
@ -71,3 +72,8 @@ show tables;
|
|||
Tables_in_test
|
||||
delete from mysql.user where user=_binary"test";
|
||||
flush privileges;
|
||||
create table t1 (id integer not null auto_increment primary key);
|
||||
create temporary table t2(id integer not null auto_increment primary key);
|
||||
set @id := 1;
|
||||
delete from t1 where id like @id;
|
||||
drop table t1;
|
||||
|
|
|
|||
|
|
@ -955,6 +955,10 @@ char_length(a) length(a) a
|
|||
2 4 ан
|
||||
drop table t1;
|
||||
set names utf8;
|
||||
select 'andre%' like 'andreñ%' escape 'ñ';
|
||||
'andre%' like 'andreñ%' escape 'ñ'
|
||||
1
|
||||
set names utf8;
|
||||
select 'a\\' like 'a\\';
|
||||
'a\\' like 'a\\'
|
||||
1
|
||||
|
|
|
|||
|
|
@ -469,6 +469,15 @@ select collation(group_concat(a,b)) from t1;
|
|||
ERROR HY000: Illegal mix of collations (cp1250_general_ci,IMPLICIT) and (koi8r_general_ci,IMPLICIT) for operation 'group_concat'
|
||||
drop table t1;
|
||||
drop table t2;
|
||||
CREATE TABLE t1 (a CHAR(10) CHARACTER SET cp850);
|
||||
INSERT INTO t1 VALUES ('Ŕ');
|
||||
SELECT a FROM t1;
|
||||
a
|
||||
Ŕ
|
||||
SELECT GROUP_CONCAT(a) FROM t1;
|
||||
GROUP_CONCAT(a)
|
||||
Ŕ
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (id int);
|
||||
SELECT GROUP_CONCAT(id) AS gc FROM t1 HAVING gc IS NULL;
|
||||
gc
|
||||
|
|
@ -567,3 +576,23 @@ group_concat('x')
|
|||
NULL
|
||||
1
|
||||
drop table t1;
|
||||
CREATE TABLE t1 (id int, a varchar(9));
|
||||
INSERT INTO t1 VALUES
|
||||
(2, ''), (1, ''), (2, 'x'), (1, 'y'), (3, 'z'), (3, '');
|
||||
SELECT GROUP_CONCAT(a) FROM t1;
|
||||
GROUP_CONCAT(a)
|
||||
,,x,y,z,
|
||||
SELECT GROUP_CONCAT(a ORDER BY a) FROM t1;
|
||||
GROUP_CONCAT(a ORDER BY a)
|
||||
,,,x,y,z
|
||||
SELECT GROUP_CONCAT(a) FROM t1 GROUP BY id;
|
||||
GROUP_CONCAT(a)
|
||||
,y
|
||||
,x
|
||||
z,
|
||||
SELECT GROUP_CONCAT(a ORDER BY a) FROM t1 GROUP BY id;
|
||||
GROUP_CONCAT(a ORDER BY a)
|
||||
,y
|
||||
,x
|
||||
,z
|
||||
DROP TABLE t1;
|
||||
|
|
|
|||
|
|
@ -158,3 +158,10 @@ DROP TABLE t1;
|
|||
select _cp866'aaaaaaaaa' like _cp866'%aaaa%' collate cp866_bin;
|
||||
_cp866'aaaaaaaaa' like _cp866'%aaaa%' collate cp866_bin
|
||||
1
|
||||
set names koi8r;
|
||||
select 'andre%' like 'andreÊ%' escape 'Ê';
|
||||
'andre%' like 'andreÊ%' escape 'Ê'
|
||||
1
|
||||
select _cp1251'andre%' like convert('andreÊ%' using cp1251) escape 'Ê';
|
||||
_cp1251'andre%' like convert('andreÊ%' using cp1251) escape 'Ê'
|
||||
1
|
||||
|
|
|
|||
|
|
@ -766,6 +766,15 @@ n
|
|||
Warnings:
|
||||
Warning 1052 Column 'n' in group statement is ambiguous
|
||||
DROP TABLE t1;
|
||||
create table t1(f1 varchar(5) key);
|
||||
insert into t1 values (1),(2);
|
||||
select sql_buffer_result max(f1) is null from t1;
|
||||
max(f1) is null
|
||||
0
|
||||
select sql_buffer_result max(f1)+1 from t1;
|
||||
max(f1)+1
|
||||
3
|
||||
drop table t1;
|
||||
create table t1 (c1 char(3), c2 char(3));
|
||||
create table t2 (c3 char(3), c4 char(3));
|
||||
insert into t1 values ('aaa', 'bb1'), ('aaa', 'bb2');
|
||||
|
|
|
|||
|
|
@ -979,3 +979,14 @@ WHERE TABLE_SCHEMA='test' AND TABLE_TYPE='BASE TABLE');
|
|||
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
|
||||
t1 MyISAM 10 Fixed 0 0 0 # 1024 0 NULL # # NULL latin1_swedish_ci NULL
|
||||
t2 MyISAM 10 Fixed 0 0 0 # 1024 0 NULL # # NULL latin1_swedish_ci NULL
|
||||
DROP TABLE t1,t2;
|
||||
create table t1(f1 int);
|
||||
create view v1 (c) as select f1 from t1;
|
||||
select database();
|
||||
database()
|
||||
NULL
|
||||
show fields from test.v1;
|
||||
Field Type Null Key Default Extra
|
||||
c int(11) YES NULL
|
||||
drop view v1;
|
||||
drop table t1;
|
||||
|
|
|
|||
|
|
@ -200,7 +200,7 @@ INSERT INTO t1 VALUES (10363,'Tecniques de Comunicacio Oral i Escrita','Tecnicas
|
|||
INSERT INTO t1 VALUES (11403,'Projecte Fi de Carrera','Proyecto Fin de Carrera','Projecte Fi de Carrera','PFC',9.0,NULL,NULL,NULL);
|
||||
INSERT INTO t1 VALUES (11404,'+lgebra lineal','Algebra lineal','+lgebra lineal','+lgebra lineal',15.0,NULL,NULL,NULL);
|
||||
INSERT INTO t1 VALUES (11405,'+lgebra lineal','Algebra lineal','+lgebra lineal','+lgebra lineal',18.0,NULL,NULL,NULL);
|
||||
INSERT INTO t1 VALUES (11406,'Calcul Infinitesimal','Cßlculo Infinitesimal','Calcul Infinitesimal','Calcul Infinitesimal',15.0,NULL,NULL,NULL);
|
||||
INSERT INTO t1 VALUES (11406,'Calcul Infinitesimal','Cßlculo Infinitesimal','Calcul Infinitesimal','Calcul Infinitesimal',15.0,NULL,NULL,NULL);
|
||||
CREATE TABLE t2 (
|
||||
idAssignatura int(11) DEFAULT '0' NOT NULL,
|
||||
Grup int(11) DEFAULT '0' NOT NULL,
|
||||
|
|
@ -1001,3 +1001,136 @@ SELECT * FROM t1 LEFT JOIN t2 ON (c11=c21 AND c21=30) WHERE c11=40;
|
|||
c11 c21
|
||||
40 NULL
|
||||
DROP TABLE t1, t2;
|
||||
CREATE TABLE t1 (a int PRIMARY KEY, b int);
|
||||
CREATE TABLE t2 (a int PRIMARY KEY, b int);
|
||||
INSERT INTO t1 VALUES (1,2), (2,1), (3,2), (4,3), (5,6), (6,5), (7,8), (8,7), (9,10);
|
||||
INSERT INTO t2 VALUES (3,0), (4,1), (6,4), (7,5);
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t2.b <= t1.a AND t1.a <= t1.b;
|
||||
a b a b
|
||||
7 8 7 5
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a BETWEEN t2.b AND t1.b;
|
||||
a b a b
|
||||
7 8 7 5
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE NOT(t1.a NOT BETWEEN t2.b AND t1.b);
|
||||
a b a b
|
||||
7 8 7 5
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t2.b > t1.a OR t1.a > t1.b;
|
||||
a b a b
|
||||
2 1 NULL NULL
|
||||
3 2 3 0
|
||||
4 3 4 1
|
||||
6 5 6 4
|
||||
8 7 NULL NULL
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a NOT BETWEEN t2.b AND t1.b;
|
||||
a b a b
|
||||
2 1 NULL NULL
|
||||
3 2 3 0
|
||||
4 3 4 1
|
||||
6 5 6 4
|
||||
8 7 NULL NULL
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE NOT(t1.a BETWEEN t2.b AND t1.b);
|
||||
a b a b
|
||||
2 1 NULL NULL
|
||||
3 2 3 0
|
||||
4 3 4 1
|
||||
6 5 6 4
|
||||
8 7 NULL NULL
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a = t2.a OR t2.b > t1.a OR t1.a > t1.b;
|
||||
a b a b
|
||||
2 1 NULL NULL
|
||||
3 2 3 0
|
||||
4 3 4 1
|
||||
6 5 6 4
|
||||
7 8 7 5
|
||||
8 7 NULL NULL
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE NOT(t1.a != t2.a AND t1.a BETWEEN t2.b AND t1.b);
|
||||
a b a b
|
||||
2 1 NULL NULL
|
||||
3 2 3 0
|
||||
4 3 4 1
|
||||
6 5 6 4
|
||||
7 8 7 5
|
||||
8 7 NULL NULL
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a = t2.a AND (t2.b > t1.a OR t1.a > t1.b);
|
||||
a b a b
|
||||
3 2 3 0
|
||||
4 3 4 1
|
||||
6 5 6 4
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE NOT(t1.a != t2.a OR t1.a BETWEEN t2.b AND t1.b);
|
||||
a b a b
|
||||
3 2 3 0
|
||||
4 3 4 1
|
||||
6 5 6 4
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a = t2.a OR t1.a = t2.b;
|
||||
a b a b
|
||||
3 2 3 0
|
||||
4 3 4 1
|
||||
6 5 6 4
|
||||
7 8 7 5
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a IN(t2.a, t2.b);
|
||||
a b a b
|
||||
3 2 3 0
|
||||
4 3 4 1
|
||||
6 5 6 4
|
||||
7 8 7 5
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE NOT(t1.a NOT IN(t2.a, t2.b));
|
||||
a b a b
|
||||
3 2 3 0
|
||||
4 3 4 1
|
||||
6 5 6 4
|
||||
7 8 7 5
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a != t1.b AND t1.a != t2.b;
|
||||
a b a b
|
||||
3 2 3 0
|
||||
4 3 4 1
|
||||
6 5 6 4
|
||||
7 8 7 5
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a NOT IN(t1.b, t2.b);
|
||||
a b a b
|
||||
3 2 3 0
|
||||
4 3 4 1
|
||||
6 5 6 4
|
||||
7 8 7 5
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE NOT(t1.a IN(t1.b, t2.b));
|
||||
a b a b
|
||||
3 2 3 0
|
||||
4 3 4 1
|
||||
6 5 6 4
|
||||
7 8 7 5
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t2.a != t2.b OR (t1.a != t2.a AND t1.a != t2.b);
|
||||
a b a b
|
||||
3 2 3 0
|
||||
4 3 4 1
|
||||
6 5 6 4
|
||||
7 8 7 5
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE NOT(t2.a = t2.b AND t1.a IN(t2.a, t2.b));
|
||||
a b a b
|
||||
3 2 3 0
|
||||
4 3 4 1
|
||||
6 5 6 4
|
||||
7 8 7 5
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t2.a != t2.b AND t1.a != t1.b AND t1.a != t2.b;
|
||||
a b a b
|
||||
3 2 3 0
|
||||
4 3 4 1
|
||||
6 5 6 4
|
||||
7 8 7 5
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE NOT(t2.a = t2.b OR t1.a IN(t1.b, t2.b));
|
||||
a b a b
|
||||
3 2 3 0
|
||||
4 3 4 1
|
||||
6 5 6 4
|
||||
7 8 7 5
|
||||
EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a = t2.a OR t1.a = t2.b;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t2 ALL PRIMARY NULL NULL NULL 4 Using where
|
||||
1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.a 1
|
||||
EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a IN(t2.a, t2.b);
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t2 ALL PRIMARY NULL NULL NULL 4 Using where
|
||||
1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.a 1
|
||||
EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a > IF(t1.a = t2.b-2, t2.b, t2.b-1);
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t2 ALL PRIMARY NULL NULL NULL 4 Using where
|
||||
1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.a 1
|
||||
DROP TABLE t1,t2;
|
||||
|
|
|
|||
|
|
@ -555,6 +555,31 @@ IFNULL(a, 'TEST') COALESCE(b, 'TEST')
|
|||
4 TEST
|
||||
TEST TEST
|
||||
DROP TABLE t1,t2;
|
||||
CREATE TABLE t1 (a INT(10) NOT NULL, b INT(10) NOT NULL);
|
||||
INSERT INTO t1 VALUES (1, 1);
|
||||
INSERT INTO t1 VALUES (1, 2);
|
||||
SELECT a, b, a AS c, COUNT(*) AS count FROM t1 GROUP BY a, b, c WITH ROLLUP;
|
||||
a b c count
|
||||
1 1 1 1
|
||||
1 1 NULL 1
|
||||
1 2 1 1
|
||||
1 2 NULL 1
|
||||
1 NULL NULL 2
|
||||
NULL NULL NULL 2
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a int(11) NOT NULL);
|
||||
INSERT INTO t1 VALUES (1),(2);
|
||||
SELECT * FROM (SELECT a, a + 1, COUNT(*) FROM t1 GROUP BY a WITH ROLLUP) t;
|
||||
a a + 1 COUNT(*)
|
||||
1 2 1
|
||||
2 3 1
|
||||
NULL NULL 2
|
||||
SELECT * FROM (SELECT a, LENGTH(a), COUNT(*) FROM t1 GROUP BY a WITH ROLLUP) t;
|
||||
a LENGTH(a) COUNT(*)
|
||||
1 1 1
|
||||
2 1 1
|
||||
NULL NULL 2
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1(id int, type char(1));
|
||||
INSERT INTO t1 VALUES
|
||||
(1,"A"),(2,"C"),(3,"A"),(4,"A"),(5,"B"),
|
||||
|
|
@ -577,15 +602,19 @@ id select_type table type possible_keys key key_len ref rows Extra
|
|||
1 PRIMARY t1 ALL NULL NULL NULL NULL 10 Using filesort
|
||||
DROP VIEW v1;
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a INT(10) NOT NULL, b INT(10) NOT NULL);
|
||||
INSERT INTO t1 VALUES (1, 1);
|
||||
INSERT INTO t1 VALUES (1, 2);
|
||||
SELECT a, b, a AS c, COUNT(*) AS count FROM t1 GROUP BY a, b, c WITH ROLLUP;
|
||||
a b c count
|
||||
1 1 1 1
|
||||
1 1 NULL 1
|
||||
1 2 1 1
|
||||
1 2 NULL 1
|
||||
1 NULL NULL 2
|
||||
NULL NULL NULL 2
|
||||
CREATE TABLE t1 (a int(11) NOT NULL);
|
||||
INSERT INTO t1 VALUES (1),(2);
|
||||
CREATE VIEW v1 AS
|
||||
SELECT a, LENGTH(a), COUNT(*) FROM t1 GROUP BY a WITH ROLLUP;
|
||||
DESC v1;
|
||||
Field Type Null Key Default Extra
|
||||
a bigint(11) YES NULL
|
||||
LENGTH(a) bigint(10) YES NULL
|
||||
COUNT(*) bigint(21) NO 0
|
||||
SELECT * FROM v1;
|
||||
a LENGTH(a) COUNT(*)
|
||||
1 1 1
|
||||
2 1 1
|
||||
NULL NULL 2
|
||||
DROP VIEW v1;
|
||||
DROP TABLE t1;
|
||||
|
|
|
|||
|
|
@ -773,6 +773,14 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp
|
|||
select ? from t1;
|
||||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? from t1' at line 1
|
||||
drop table t1;
|
||||
CREATE TABLE b12651_T1(a int) ENGINE=MYISAM;
|
||||
CREATE TABLE b12651_T2(b int) ENGINE=MYISAM;
|
||||
CREATE VIEW b12651_V1 as SELECT b FROM b12651_T2;
|
||||
PREPARE b12651 FROM 'SELECT 1 FROM b12651_T1 WHERE a IN (SELECT b FROM b12651_V1)';
|
||||
EXECUTE b12651;
|
||||
1
|
||||
DROP VIEW b12651_V1;
|
||||
DROP TABLE b12651_T1, b12651_T2;
|
||||
prepare stmt from "select @@time_zone";
|
||||
execute stmt;
|
||||
@@time_zone
|
||||
|
|
|
|||
|
|
@ -156,3 +156,60 @@ slave: 6
|
|||
drop procedure p1;
|
||||
drop function f1;
|
||||
drop table t1,t2;
|
||||
create table t1 (a int);
|
||||
create procedure p1()
|
||||
begin
|
||||
insert into t1 values(@x);
|
||||
set @x=@x+1;
|
||||
insert into t1 values(@x);
|
||||
if (f2()) then
|
||||
insert into t1 values(1243);
|
||||
end if;
|
||||
end//
|
||||
create function f2() returns int
|
||||
begin
|
||||
insert into t1 values(@z);
|
||||
set @z=@z+1;
|
||||
insert into t1 values(@z);
|
||||
return 0;
|
||||
end//
|
||||
create function f1() returns int
|
||||
begin
|
||||
insert into t1 values(@y);
|
||||
call p1();
|
||||
return 0;
|
||||
end//
|
||||
set @x=10;
|
||||
set @y=20;
|
||||
set @z=100;
|
||||
select f1();
|
||||
f1()
|
||||
0
|
||||
set @x=30;
|
||||
call p1();
|
||||
select 'master', a from t1;
|
||||
master a
|
||||
master 20
|
||||
master 10
|
||||
master 11
|
||||
master 100
|
||||
master 101
|
||||
master 30
|
||||
master 31
|
||||
master 101
|
||||
master 102
|
||||
select 'slave', a from t1;
|
||||
slave a
|
||||
slave 20
|
||||
slave 10
|
||||
slave 11
|
||||
slave 100
|
||||
slave 101
|
||||
slave 30
|
||||
slave 31
|
||||
slave 101
|
||||
slave 102
|
||||
drop table t1;
|
||||
drop function f1;
|
||||
drop function f2;
|
||||
drop procedure p1;
|
||||
|
|
|
|||
|
|
@ -2897,3 +2897,18 @@ select * from t1 natural join t2 where a = 'b';
|
|||
a
|
||||
b
|
||||
drop table t1, t2;
|
||||
CREATE TABLE t1 (`id` TINYINT);
|
||||
CREATE TABLE t2 (`id` TINYINT);
|
||||
CREATE TABLE t3 (`id` TINYINT);
|
||||
INSERT INTO t1 VALUES (1),(2),(3);
|
||||
INSERT INTO t2 VALUES (2);
|
||||
INSERT INTO t3 VALUES (3);
|
||||
SELECT t1.id,t3.id FROM t1 JOIN t2 ON (t2.id=t1.id) LEFT JOIN t3 USING (id);
|
||||
ERROR 23000: Column 'id' in from clause is ambiguous
|
||||
SELECT t1.id,t3.id FROM t1 JOIN t2 ON (t2.notacolumn=t1.id) LEFT JOIN t3 USING (id);
|
||||
ERROR 23000: Column 'id' in from clause is ambiguous
|
||||
SELECT id,t3.id FROM t1 JOIN t2 ON (t2.id=t1.id) LEFT JOIN t3 USING (id);
|
||||
ERROR 23000: Column 'id' in from clause is ambiguous
|
||||
SELECT id,t3.id FROM (t1 JOIN t2 ON (t2.id=t1.id)) LEFT JOIN t3 USING (id);
|
||||
ERROR 23000: Column 'id' in from clause is ambiguous
|
||||
drop table t1, t2, t3;
|
||||
|
|
|
|||
|
|
@ -765,3 +765,24 @@ OPTIMIZE TABLE t1;
|
|||
RETURN 1;
|
||||
END|
|
||||
ERROR 0A000: OPTIMIZE TABLE is not allowed in stored procedures
|
||||
DROP FUNCTION IF EXISTS bug12995|
|
||||
CREATE FUNCTION bug12995() RETURNS INT
|
||||
BEGIN
|
||||
HANDLER t1 OPEN;
|
||||
RETURN 1;
|
||||
END|
|
||||
ERROR 0A000: HANDLER is not allowed in stored procedures
|
||||
CREATE FUNCTION bug12995() RETURNS INT
|
||||
BEGIN
|
||||
HANDLER t1 READ FIRST;
|
||||
RETURN 1;
|
||||
END|
|
||||
ERROR 0A000: HANDLER is not allowed in stored procedures
|
||||
CREATE FUNCTION bug12995() RETURNS INT
|
||||
BEGIN
|
||||
HANDLER t1 CLOSE;
|
||||
RETURN 1;
|
||||
END|
|
||||
ERROR 0A000: HANDLER is not allowed in stored procedures
|
||||
SELECT bug12995()|
|
||||
ERROR 42000: FUNCTION test.bug12995 does not exist
|
||||
|
|
|
|||
|
|
@ -3085,6 +3085,19 @@ column_name bug10055(t.column_name)
|
|||
id id
|
||||
data data
|
||||
drop function bug10055|
|
||||
drop procedure if exists bug12297|
|
||||
create procedure bug12297(lim int)
|
||||
begin
|
||||
set @x = 0;
|
||||
repeat
|
||||
insert into t1(id,data)
|
||||
values('aa', @x);
|
||||
set @x = @x + 1;
|
||||
until @x >= lim
|
||||
end repeat;
|
||||
end|
|
||||
call bug12297(10)|
|
||||
drop procedure bug12297|
|
||||
drop function if exists f_bug11247|
|
||||
drop procedure if exists p_bug11247|
|
||||
create function f_bug11247(param int)
|
||||
|
|
@ -3193,4 +3206,23 @@ set f1= concat( 'hello', f1 );
|
|||
return f1;
|
||||
end|
|
||||
drop function bug9048|
|
||||
drop procedure if exists bug12849_1|
|
||||
create procedure bug12849_1(inout x char) select x into x|
|
||||
set @var='a'|
|
||||
call bug12849_1(@var)|
|
||||
select @var|
|
||||
@var
|
||||
a
|
||||
drop procedure bug12849_1|
|
||||
drop procedure if exists bug12849_2|
|
||||
create procedure bug12849_2(inout foo varchar(15))
|
||||
begin
|
||||
select concat(foo, foo) INTO foo;
|
||||
end|
|
||||
set @var='abcd'|
|
||||
call bug12849_2(@var)|
|
||||
select @var|
|
||||
@var
|
||||
abcdabcd
|
||||
drop procedure bug12849_2|
|
||||
drop table t1,t2;
|
||||
|
|
|
|||
|
|
@ -984,3 +984,35 @@ t1 CREATE TABLE `t1` (
|
|||
`f1` decimal(10,0) unsigned zerofill NOT NULL default '0000000000'
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
drop table t1;
|
||||
drop procedure if exists wg2;
|
||||
Warnings:
|
||||
Note 1305 PROCEDURE wg2 does not exist
|
||||
create procedure wg2()
|
||||
begin
|
||||
declare v int default 1;
|
||||
declare tdec decimal(5) default 0;
|
||||
while v <= 9 do set tdec =tdec * 10;
|
||||
select v, tdec;
|
||||
set v = v + 1;
|
||||
end while;
|
||||
end//
|
||||
call wg2()//
|
||||
v tdec
|
||||
1 0
|
||||
v tdec
|
||||
2 0
|
||||
v tdec
|
||||
3 0
|
||||
v tdec
|
||||
4 0
|
||||
v tdec
|
||||
5 0
|
||||
v tdec
|
||||
6 0
|
||||
v tdec
|
||||
7 0
|
||||
v tdec
|
||||
8 0
|
||||
v tdec
|
||||
9 0
|
||||
drop procedure wg2;
|
||||
|
|
|
|||
|
|
@ -545,3 +545,10 @@ select @@max_heap_table_size > 0;
|
|||
select @@have_innodb;
|
||||
@@have_innodb
|
||||
#
|
||||
select @@character_set_system;
|
||||
@@character_set_system
|
||||
utf8
|
||||
set global character_set_system = latin1;
|
||||
ERROR HY000: Variable 'character_set_system' is a read only variable
|
||||
set @@global.version_compile_os='234';
|
||||
ERROR HY000: Variable 'version_compile_os' is a read only variable
|
||||
|
|
|
|||
|
|
@ -2151,6 +2151,15 @@ select * from v1;
|
|||
strcmp(f1,'a')
|
||||
drop view v1;
|
||||
drop table t1;
|
||||
create table t1 (f1 int, f2 int,f3 int);
|
||||
insert into t1 values (1,10,20),(2,0,0);
|
||||
create view v1 as select * from t1;
|
||||
select if(sum(f1)>1,f2,f3) from v1 group by f1;
|
||||
if(sum(f1)>1,f2,f3)
|
||||
20
|
||||
0
|
||||
drop view v1;
|
||||
drop table t1;
|
||||
create table t1 (
|
||||
r_object_id char(16) NOT NULL,
|
||||
group_name varchar(32) NOT NULL
|
||||
|
|
|
|||
|
|
@ -6,6 +6,10 @@
|
|||
# This test makes no sense with the embedded server
|
||||
--source include/not_embedded.inc
|
||||
|
||||
--disable_warnings
|
||||
drop table if exists t1,t2;
|
||||
--enable_warnings
|
||||
|
||||
#connect (con1,localhost,root,,"");
|
||||
#show tables;
|
||||
connect (con1,localhost,root,,mysql);
|
||||
|
|
@ -77,4 +81,18 @@ show tables;
|
|||
delete from mysql.user where user=_binary"test";
|
||||
flush privileges;
|
||||
|
||||
#
|
||||
# Bug#12517: Clear user variables and replication events before
|
||||
# closing temp tables in thread cleanup.
|
||||
connect (con2,localhost,root,,test);
|
||||
connection con2;
|
||||
create table t1 (id integer not null auto_increment primary key);
|
||||
create temporary table t2(id integer not null auto_increment primary key);
|
||||
set @id := 1;
|
||||
delete from t1 where id like @id;
|
||||
disconnect con2;
|
||||
--sleep 5
|
||||
connection default;
|
||||
drop table t1;
|
||||
|
||||
# End of 4.1 tests
|
||||
|
|
|
|||
|
|
@ -810,6 +810,12 @@ alter table t1 modify a char(2) character set utf8;
|
|||
select char_length(a), length(a), a from t1 order by a;
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# Bugs#12611
|
||||
# ESCAPE + LIKE do not work when the escape char is a multibyte one
|
||||
#
|
||||
set names utf8;
|
||||
select 'andre%' like 'andreñ%' escape 'ñ';
|
||||
|
||||
#
|
||||
# Bugs#11754: SET NAMES utf8 followed by SELECT "A\\" LIKE "A\\" returns 0
|
||||
|
|
|
|||
|
|
@ -281,6 +281,16 @@ select collation(group_concat(a,b)) from t1;
|
|||
drop table t1;
|
||||
drop table t2;
|
||||
|
||||
#
|
||||
# Bug #12829
|
||||
# Cannot convert the charset of a GROUP_CONCAT result
|
||||
#
|
||||
CREATE TABLE t1 (a CHAR(10) CHARACTER SET cp850);
|
||||
INSERT INTO t1 VALUES ('À');
|
||||
SELECT a FROM t1;
|
||||
SELECT GROUP_CONCAT(a) FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
#
|
||||
# bug #7769: group_concat returning null is checked in having
|
||||
#
|
||||
|
|
@ -363,4 +373,20 @@ select * from (select group_concat(a) from t1) t2;
|
|||
select group_concat('x') UNION ALL select 1;
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# Bug #12863 : missing separators after first empty cancatanated elements
|
||||
#
|
||||
|
||||
CREATE TABLE t1 (id int, a varchar(9));
|
||||
INSERT INTO t1 VALUES
|
||||
(2, ''), (1, ''), (2, 'x'), (1, 'y'), (3, 'z'), (3, '');
|
||||
|
||||
SELECT GROUP_CONCAT(a) FROM t1;
|
||||
SELECT GROUP_CONCAT(a ORDER BY a) FROM t1;
|
||||
|
||||
SELECT GROUP_CONCAT(a) FROM t1 GROUP BY id;
|
||||
SELECT GROUP_CONCAT(a ORDER BY a) FROM t1 GROUP BY id;
|
||||
|
||||
DROP TABLE t1;
|
||||
|
||||
# End of 4.1 tests
|
||||
|
|
|
|||
|
|
@ -96,4 +96,21 @@ DROP TABLE t1;
|
|||
#
|
||||
select _cp866'aaaaaaaaa' like _cp866'%aaaa%' collate cp866_bin;
|
||||
|
||||
#
|
||||
# Check 8bit escape character
|
||||
#
|
||||
set names koi8r;
|
||||
select 'andre%' like 'andreÊ%' escape 'Ê';
|
||||
|
||||
# Check 8bit escape character with charset conversion:
|
||||
# For "a LIKE b ESCAPE c" expressions,
|
||||
# escape character is converted into the operation character set,
|
||||
# which is result of aggregation of character sets of "a" and "b".
|
||||
# "c" itself doesn't take part in aggregation, because its collation
|
||||
# doesn't matter, escape character is always compared binary.
|
||||
# In the example below, escape character is converted from koi8r into cp1251:
|
||||
#
|
||||
select _cp1251'andre%' like convert('andreÊ%' using cp1251) escape 'Ê';
|
||||
|
||||
#
|
||||
# End of 4.1 tests
|
||||
|
|
|
|||
|
|
@ -580,7 +580,6 @@ SELECT COUNT(DISTINCT(t1.id)), LEFT(err_comment, 256) AS comment
|
|||
|
||||
DROP TABLE t1, t2;
|
||||
|
||||
|
||||
#
|
||||
# Bug #12266 GROUP BY expression on DATE column produces result with
|
||||
# reduced length
|
||||
|
|
@ -602,6 +601,16 @@ SELECT n+1 AS n FROM t1 GROUP BY n;
|
|||
--enable_ps_protocol
|
||||
DROP TABLE t1;
|
||||
|
||||
#
|
||||
# BUG#12695: Item_func_isnull::update_used_tables
|
||||
# did not update const_item_cache
|
||||
#
|
||||
create table t1(f1 varchar(5) key);
|
||||
insert into t1 values (1),(2);
|
||||
select sql_buffer_result max(f1) is null from t1;
|
||||
select sql_buffer_result max(f1)+1 from t1;
|
||||
drop table t1;
|
||||
|
||||
# End of 4.1 tests
|
||||
|
||||
#
|
||||
|
|
|
|||
|
|
@ -665,4 +665,16 @@ SHOW TABLE STATUS FROM test
|
|||
WHERE name IN ( SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
|
||||
WHERE TABLE_SCHEMA='test' AND TABLE_TYPE='BASE TABLE');
|
||||
|
||||
DROP TABLE t1,t2
|
||||
DROP TABLE t1,t2;
|
||||
|
||||
#
|
||||
# Bug #12905 show fields from view behaving erratically with current database
|
||||
#
|
||||
create table t1(f1 int);
|
||||
create view v1 (c) as select f1 from t1;
|
||||
connect (con5,localhost,root,,*NO-ONE*);
|
||||
select database();
|
||||
show fields from test.v1;
|
||||
connection default;
|
||||
drop view v1;
|
||||
drop table t1;
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ INSERT INTO t1 VALUES (10363,'Tecniques de Comunicacio Oral i Escrita','Tecnicas
|
|||
INSERT INTO t1 VALUES (11403,'Projecte Fi de Carrera','Proyecto Fin de Carrera','Projecte Fi de Carrera','PFC',9.0,NULL,NULL,NULL);
|
||||
INSERT INTO t1 VALUES (11404,'+lgebra lineal','Algebra lineal','+lgebra lineal','+lgebra lineal',15.0,NULL,NULL,NULL);
|
||||
INSERT INTO t1 VALUES (11405,'+lgebra lineal','Algebra lineal','+lgebra lineal','+lgebra lineal',18.0,NULL,NULL,NULL);
|
||||
INSERT INTO t1 VALUES (11406,'Calcul Infinitesimal','Cßlculo Infinitesimal','Calcul Infinitesimal','Calcul Infinitesimal',15.0,NULL,NULL,NULL);
|
||||
INSERT INTO t1 VALUES (11406,'Calcul Infinitesimal','Cßlculo Infinitesimal','Calcul Infinitesimal','Calcul Infinitesimal',15.0,NULL,NULL,NULL);
|
||||
|
||||
CREATE TABLE t2 (
|
||||
idAssignatura int(11) DEFAULT '0' NOT NULL,
|
||||
|
|
@ -590,7 +590,6 @@ INSERT INTO t2 VALUES("0", "EN", "0-EN");
|
|||
INSERT INTO t2 VALUES("0", "SV", "0-SV");
|
||||
INSERT INTO t2 VALUES("10", "EN", "10-EN");
|
||||
INSERT INTO t2 VALUES("10", "SV", "10-SV");
|
||||
|
||||
SELECT t1.id, t1.text_id, t2.text_data
|
||||
FROM t1 LEFT JOIN t2
|
||||
ON t1.text_id = t2.text_id
|
||||
|
|
@ -713,3 +712,49 @@ INSERT INTO t1 VALUES (30), (40), (50);
|
|||
INSERT INTO t2 VALUES (300), (400), (500);
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON (c11=c21 AND c21=30) WHERE c11=40;
|
||||
DROP TABLE t1, t2;
|
||||
#
|
||||
# Test for bugs
|
||||
# #12101: erroneously applied outer join elimination in case of WHERE NOT BETWEEN
|
||||
# #12102: erroneously missing outer join elimination in case of WHERE IN/IF
|
||||
#
|
||||
|
||||
CREATE TABLE t1 (a int PRIMARY KEY, b int);
|
||||
CREATE TABLE t2 (a int PRIMARY KEY, b int);
|
||||
|
||||
INSERT INTO t1 VALUES (1,2), (2,1), (3,2), (4,3), (5,6), (6,5), (7,8), (8,7), (9,10);
|
||||
INSERT INTO t2 VALUES (3,0), (4,1), (6,4), (7,5);
|
||||
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t2.b <= t1.a AND t1.a <= t1.b;
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a BETWEEN t2.b AND t1.b;
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE NOT(t1.a NOT BETWEEN t2.b AND t1.b);
|
||||
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t2.b > t1.a OR t1.a > t1.b;
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a NOT BETWEEN t2.b AND t1.b;
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE NOT(t1.a BETWEEN t2.b AND t1.b);
|
||||
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a = t2.a OR t2.b > t1.a OR t1.a > t1.b;
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE NOT(t1.a != t2.a AND t1.a BETWEEN t2.b AND t1.b);
|
||||
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a = t2.a AND (t2.b > t1.a OR t1.a > t1.b);
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE NOT(t1.a != t2.a OR t1.a BETWEEN t2.b AND t1.b);
|
||||
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a = t2.a OR t1.a = t2.b;
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a IN(t2.a, t2.b);
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE NOT(t1.a NOT IN(t2.a, t2.b));
|
||||
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a != t1.b AND t1.a != t2.b;
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a NOT IN(t1.b, t2.b);
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE NOT(t1.a IN(t1.b, t2.b));
|
||||
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t2.a != t2.b OR (t1.a != t2.a AND t1.a != t2.b);
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE NOT(t2.a = t2.b AND t1.a IN(t2.a, t2.b));
|
||||
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t2.a != t2.b AND t1.a != t1.b AND t1.a != t2.b;
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE NOT(t2.a = t2.b OR t1.a IN(t1.b, t2.b));
|
||||
|
||||
EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a = t2.a OR t1.a = t2.b;
|
||||
EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a IN(t2.a, t2.b);
|
||||
EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a > IF(t1.a = t2.b-2, t2.b, t2.b-1);
|
||||
|
||||
DROP TABLE t1,t2;
|
||||
|
||||
|
|
|
|||
|
|
@ -250,6 +250,32 @@ SELECT IFNULL(a, 'TEST'), COALESCE(b, 'TEST') FROM t2
|
|||
|
||||
DROP TABLE t1,t2;
|
||||
|
||||
#
|
||||
# Test for bug #11543: ROLLUP query with a repeated column in GROUP BY
|
||||
#
|
||||
|
||||
CREATE TABLE t1 (a INT(10) NOT NULL, b INT(10) NOT NULL);
|
||||
INSERT INTO t1 VALUES (1, 1);
|
||||
INSERT INTO t1 VALUES (1, 2);
|
||||
|
||||
SELECT a, b, a AS c, COUNT(*) AS count FROM t1 GROUP BY a, b, c WITH ROLLUP;
|
||||
|
||||
DROP TABLE t1;
|
||||
|
||||
# Bug #12885(1): derived table specified by a subquery with
|
||||
# ROLLUP over expressions on not nullable group by attributes
|
||||
#
|
||||
|
||||
CREATE TABLE t1 (a int(11) NOT NULL);
|
||||
INSERT INTO t1 VALUES (1),(2);
|
||||
|
||||
SELECT * FROM (SELECT a, a + 1, COUNT(*) FROM t1 GROUP BY a WITH ROLLUP) t;
|
||||
SELECT * FROM (SELECT a, LENGTH(a), COUNT(*) FROM t1 GROUP BY a WITH ROLLUP) t;
|
||||
|
||||
DROP TABLE t1;
|
||||
|
||||
# End of 4.1 tests
|
||||
|
||||
#
|
||||
# Tests for bug #11639: ROLLUP over view executed through filesort
|
||||
#
|
||||
|
|
@ -266,15 +292,20 @@ EXPLAIN SELECT type FROM v1 GROUP BY type WITH ROLLUP;
|
|||
|
||||
DROP VIEW v1;
|
||||
DROP TABLE t1;
|
||||
# Test for bug #11543: ROLLUP query with a repeated column in GROUP BY
|
||||
|
||||
#
|
||||
# Bug #12885(2): view specified by a subquery with
|
||||
# ROLLUP over expressions on not nullable group by attributes
|
||||
#
|
||||
|
||||
CREATE TABLE t1 (a INT(10) NOT NULL, b INT(10) NOT NULL);
|
||||
INSERT INTO t1 VALUES (1, 1);
|
||||
INSERT INTO t1 VALUES (1, 2);
|
||||
CREATE TABLE t1 (a int(11) NOT NULL);
|
||||
INSERT INTO t1 VALUES (1),(2);
|
||||
|
||||
SELECT a, b, a AS c, COUNT(*) AS count FROM t1 GROUP BY a, b, c WITH ROLLUP;
|
||||
CREATE VIEW v1 AS
|
||||
SELECT a, LENGTH(a), COUNT(*) FROM t1 GROUP BY a WITH ROLLUP;
|
||||
|
||||
DESC v1;
|
||||
SELECT * FROM v1;
|
||||
|
||||
DROP VIEW v1;
|
||||
DROP TABLE t1;
|
||||
|
||||
# End of 4.1 tests
|
||||
|
|
|
|||
|
|
@ -809,6 +809,21 @@ select ??;
|
|||
select ? from t1;
|
||||
--enable_ps_protocol
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# Bug#12651
|
||||
# (Crash on a PS including a subquery which is a select from a simple view)
|
||||
#
|
||||
CREATE TABLE b12651_T1(a int) ENGINE=MYISAM;
|
||||
CREATE TABLE b12651_T2(b int) ENGINE=MYISAM;
|
||||
CREATE VIEW b12651_V1 as SELECT b FROM b12651_T2;
|
||||
|
||||
PREPARE b12651 FROM 'SELECT 1 FROM b12651_T1 WHERE a IN (SELECT b FROM b12651_V1)';
|
||||
EXECUTE b12651;
|
||||
|
||||
DROP VIEW b12651_V1;
|
||||
DROP TABLE b12651_T1, b12651_T2;
|
||||
|
||||
#
|
||||
# Bug#9359 "Prepared statements take snapshot of system vars at PREPARE
|
||||
# time"
|
||||
|
|
|
|||
|
|
@ -152,4 +152,52 @@ drop procedure p1;
|
|||
drop function f1;
|
||||
drop table t1,t2;
|
||||
|
||||
# BUG#12637: User variables + SPs replication
|
||||
create table t1 (a int);
|
||||
delimiter //;
|
||||
create procedure p1()
|
||||
begin
|
||||
insert into t1 values(@x);
|
||||
set @x=@x+1;
|
||||
insert into t1 values(@x);
|
||||
if (f2()) then
|
||||
insert into t1 values(1243);
|
||||
end if;
|
||||
end//
|
||||
|
||||
create function f2() returns int
|
||||
begin
|
||||
insert into t1 values(@z);
|
||||
set @z=@z+1;
|
||||
insert into t1 values(@z);
|
||||
return 0;
|
||||
end//
|
||||
|
||||
create function f1() returns int
|
||||
begin
|
||||
insert into t1 values(@y);
|
||||
call p1();
|
||||
return 0;
|
||||
end//
|
||||
|
||||
delimiter ;//
|
||||
|
||||
set @x=10;
|
||||
set @y=20;
|
||||
set @z=100;
|
||||
select f1();
|
||||
|
||||
set @x=30;
|
||||
call p1();
|
||||
|
||||
select 'master', a from t1;
|
||||
sync_slave_with_master;
|
||||
connection slave;
|
||||
select 'slave', a from t1;
|
||||
|
||||
connection master;
|
||||
drop table t1;
|
||||
drop function f1;
|
||||
drop function f2;
|
||||
drop procedure p1;
|
||||
sync_slave_with_master;
|
||||
|
|
|
|||
|
|
@ -2465,3 +2465,25 @@ insert into t2 values ('b'),('c'),('d');
|
|||
select a from t1 natural join t2;
|
||||
select * from t1 natural join t2 where a = 'b';
|
||||
drop table t1, t2;
|
||||
|
||||
#
|
||||
# Bug #12977 Compare table names with qualifying field tables only
|
||||
# for base tables, search all nested join operands of natural joins.
|
||||
#
|
||||
|
||||
CREATE TABLE t1 (`id` TINYINT);
|
||||
CREATE TABLE t2 (`id` TINYINT);
|
||||
CREATE TABLE t3 (`id` TINYINT);
|
||||
INSERT INTO t1 VALUES (1),(2),(3);
|
||||
INSERT INTO t2 VALUES (2);
|
||||
INSERT INTO t3 VALUES (3);
|
||||
-- error 1052
|
||||
SELECT t1.id,t3.id FROM t1 JOIN t2 ON (t2.id=t1.id) LEFT JOIN t3 USING (id);
|
||||
-- error 1052
|
||||
SELECT t1.id,t3.id FROM t1 JOIN t2 ON (t2.notacolumn=t1.id) LEFT JOIN t3 USING (id);
|
||||
-- error 1052
|
||||
SELECT id,t3.id FROM t1 JOIN t2 ON (t2.id=t1.id) LEFT JOIN t3 USING (id);
|
||||
-- error 1052
|
||||
SELECT id,t3.id FROM (t1 JOIN t2 ON (t2.id=t1.id)) LEFT JOIN t3 USING (id);
|
||||
|
||||
drop table t1, t2, t3;
|
||||
|
|
|
|||
|
|
@ -1099,6 +1099,36 @@ BEGIN
|
|||
OPTIMIZE TABLE t1;
|
||||
RETURN 1;
|
||||
END|
|
||||
delimiter ;|
|
||||
|
||||
#
|
||||
# Bug##12995 "Inside function "Table 't4' was not locked with LOCK TABLES"
|
||||
#
|
||||
delimiter |;
|
||||
--disable_warnings
|
||||
DROP FUNCTION IF EXISTS bug12995|
|
||||
--enable_warnings
|
||||
--error ER_SP_BADSTATEMENT
|
||||
CREATE FUNCTION bug12995() RETURNS INT
|
||||
BEGIN
|
||||
HANDLER t1 OPEN;
|
||||
RETURN 1;
|
||||
END|
|
||||
--error ER_SP_BADSTATEMENT
|
||||
CREATE FUNCTION bug12995() RETURNS INT
|
||||
BEGIN
|
||||
HANDLER t1 READ FIRST;
|
||||
RETURN 1;
|
||||
END|
|
||||
--error ER_SP_BADSTATEMENT
|
||||
CREATE FUNCTION bug12995() RETURNS INT
|
||||
BEGIN
|
||||
HANDLER t1 CLOSE;
|
||||
RETURN 1;
|
||||
END|
|
||||
--error 1305
|
||||
SELECT bug12995()|
|
||||
delimiter ;|
|
||||
|
||||
#
|
||||
# BUG#NNNN: New bug synopsis
|
||||
|
|
|
|||
|
|
@ -3877,29 +3877,23 @@ drop function bug10055|
|
|||
# consumption by passing large input parameter.
|
||||
#
|
||||
|
||||
#
|
||||
# Note: the test is currenly disabled because of the
|
||||
# Bug #12637: SP crashes the server if it has update query with user var
|
||||
# & binlog is enabled.
|
||||
#
|
||||
|
||||
--disable_warnings
|
||||
#drop procedure if exists bug12297|
|
||||
drop procedure if exists bug12297|
|
||||
--enable_warnings
|
||||
|
||||
#create procedure bug12297(lim int)
|
||||
#begin
|
||||
# set @x = 0;
|
||||
# repeat
|
||||
# insert into t1(id,data)
|
||||
# values('aa', @x);
|
||||
# set @x = @x + 1;
|
||||
# until @x >= lim
|
||||
# end repeat;
|
||||
#end|
|
||||
create procedure bug12297(lim int)
|
||||
begin
|
||||
set @x = 0;
|
||||
repeat
|
||||
insert into t1(id,data)
|
||||
values('aa', @x);
|
||||
set @x = @x + 1;
|
||||
until @x >= lim
|
||||
end repeat;
|
||||
end|
|
||||
|
||||
#call bug12297(10)|
|
||||
#drop procedure bug12297|
|
||||
call bug12297(10)|
|
||||
drop procedure bug12297|
|
||||
|
||||
#
|
||||
# Bug #11247 "Stored procedures: Function calls in long loops leak memory"
|
||||
|
|
@ -4043,6 +4037,32 @@ begin
|
|||
end|
|
||||
drop function bug9048|
|
||||
|
||||
#
|
||||
# Bug #12849 Stored Procedure: Crash on procedure call with CHAR type
|
||||
# 'INOUT' parameter
|
||||
#
|
||||
|
||||
--disable_warnings
|
||||
drop procedure if exists bug12849_1|
|
||||
--enable_warnings
|
||||
create procedure bug12849_1(inout x char) select x into x|
|
||||
set @var='a'|
|
||||
call bug12849_1(@var)|
|
||||
select @var|
|
||||
drop procedure bug12849_1|
|
||||
|
||||
--disable_warnings
|
||||
drop procedure if exists bug12849_2|
|
||||
--enable_warnings
|
||||
create procedure bug12849_2(inout foo varchar(15))
|
||||
begin
|
||||
select concat(foo, foo) INTO foo;
|
||||
end|
|
||||
set @var='abcd'|
|
||||
call bug12849_2(@var)|
|
||||
select @var|
|
||||
drop procedure bug12849_2|
|
||||
|
||||
#
|
||||
# BUG#NNNN: New bug synopsis
|
||||
#
|
||||
|
|
|
|||
|
|
@ -1015,3 +1015,25 @@ create table t1 (
|
|||
f1 decimal (0,0) zerofill not null default 0);
|
||||
show create table t1;
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# Bug 12938 (arithmetic loop's zero)
|
||||
#
|
||||
--disable-warnings
|
||||
drop procedure if exists wg2;
|
||||
--enable-warnings
|
||||
delimiter //;
|
||||
create procedure wg2()
|
||||
begin
|
||||
declare v int default 1;
|
||||
declare tdec decimal(5) default 0;
|
||||
while v <= 9 do set tdec =tdec * 10;
|
||||
select v, tdec;
|
||||
set v = v + 1;
|
||||
end while;
|
||||
end//
|
||||
|
||||
call wg2()//
|
||||
|
||||
delimiter ;//
|
||||
drop procedure wg2;
|
||||
|
|
|
|||
|
|
@ -435,3 +435,12 @@ select @@max_heap_table_size > 0;
|
|||
|
||||
--replace_column 1 #
|
||||
select @@have_innodb;
|
||||
|
||||
#
|
||||
# Bug #11775 Variable character_set_system does not exist (sometimes)
|
||||
#
|
||||
select @@character_set_system;
|
||||
--error 1238
|
||||
set global character_set_system = latin1;
|
||||
--error 1238
|
||||
set @@global.version_compile_os='234';
|
||||
|
|
|
|||
|
|
@ -2020,6 +2020,14 @@ drop view v1;
|
|||
drop table t1;
|
||||
|
||||
#
|
||||
# Bug #12922 if(sum(),...) with group from view returns wrong results
|
||||
#
|
||||
create table t1 (f1 int, f2 int,f3 int);
|
||||
insert into t1 values (1,10,20),(2,0,0);
|
||||
create view v1 as select * from t1;
|
||||
select if(sum(f1)>1,f2,f3) from v1 group by f1;
|
||||
drop view v1;
|
||||
drop table t1;
|
||||
# BUG#12941
|
||||
#
|
||||
create table t1 (
|
||||
|
|
|
|||
269
ndb/src/ndbapi/SignalSender.cpp
Normal file
269
ndb/src/ndbapi/SignalSender.cpp
Normal file
|
|
@ -0,0 +1,269 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include "SignalSender.hpp"
|
||||
#include <NdbSleep.h>
|
||||
#include <SignalLoggerManager.hpp>
|
||||
#include <signaldata/NFCompleteRep.hpp>
|
||||
#include <signaldata/NodeFailRep.hpp>
|
||||
|
||||
SimpleSignal::SimpleSignal(bool dealloc){
|
||||
memset(this, 0, sizeof(* this));
|
||||
deallocSections = dealloc;
|
||||
}
|
||||
|
||||
SimpleSignal::~SimpleSignal(){
|
||||
if(!deallocSections)
|
||||
return;
|
||||
if(ptr[0].p != 0) delete []ptr[0].p;
|
||||
if(ptr[1].p != 0) delete []ptr[1].p;
|
||||
if(ptr[2].p != 0) delete []ptr[2].p;
|
||||
}
|
||||
|
||||
void
|
||||
SimpleSignal::set(class SignalSender& ss,
|
||||
Uint8 trace, Uint16 recBlock, Uint16 gsn, Uint32 len){
|
||||
|
||||
header.theTrace = trace;
|
||||
header.theReceiversBlockNumber = recBlock;
|
||||
header.theVerId_signalNumber = gsn;
|
||||
header.theLength = len;
|
||||
header.theSendersBlockRef = refToBlock(ss.getOwnRef());
|
||||
}
|
||||
|
||||
void
|
||||
SimpleSignal::print(FILE * out){
|
||||
fprintf(out, "---- Signal ----------------\n");
|
||||
SignalLoggerManager::printSignalHeader(out, header, 0, 0, false);
|
||||
SignalLoggerManager::printSignalData(out, header, theData);
|
||||
for(Uint32 i = 0; i<header.m_noOfSections; i++){
|
||||
Uint32 len = ptr[i].sz;
|
||||
fprintf(out, " --- Section %d size=%d ---\n", i, len);
|
||||
Uint32 * signalData = ptr[i].p;
|
||||
while(len >= 7){
|
||||
fprintf(out,
|
||||
" H\'%.8x H\'%.8x H\'%.8x H\'%.8x H\'%.8x H\'%.8x H\'%.8x\n",
|
||||
signalData[0], signalData[1], signalData[2], signalData[3],
|
||||
signalData[4], signalData[5], signalData[6]);
|
||||
len -= 7;
|
||||
signalData += 7;
|
||||
}
|
||||
if(len > 0){
|
||||
fprintf(out, " H\'%.8x", signalData[0]);
|
||||
for(Uint32 i = 1; i<len; i++)
|
||||
fprintf(out, " H\'%.8x", signalData[i]);
|
||||
fprintf(out, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SignalSender::SignalSender(TransporterFacade *facade)
|
||||
: m_lock(0)
|
||||
{
|
||||
m_cond = NdbCondition_Create();
|
||||
theFacade = facade;
|
||||
m_blockNo = theFacade->open(this, execSignal, execNodeStatus);
|
||||
assert(m_blockNo > 0);
|
||||
}
|
||||
|
||||
SignalSender::~SignalSender(){
|
||||
int i;
|
||||
if (m_lock)
|
||||
unlock();
|
||||
theFacade->close(m_blockNo,0);
|
||||
// free these _after_ closing theFacade to ensure that
|
||||
// we delete all signals
|
||||
for (i= m_jobBuffer.size()-1; i>= 0; i--)
|
||||
delete m_jobBuffer[i];
|
||||
for (i= m_usedBuffer.size()-1; i>= 0; i--)
|
||||
delete m_usedBuffer[i];
|
||||
NdbCondition_Destroy(m_cond);
|
||||
}
|
||||
|
||||
int SignalSender::lock()
|
||||
{
|
||||
if (NdbMutex_Lock(theFacade->theMutexPtr))
|
||||
return -1;
|
||||
m_lock= 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SignalSender::unlock()
|
||||
{
|
||||
if (NdbMutex_Unlock(theFacade->theMutexPtr))
|
||||
return -1;
|
||||
m_lock= 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Uint32
|
||||
SignalSender::getOwnRef() const {
|
||||
return numberToRef(m_blockNo, theFacade->ownId());
|
||||
}
|
||||
|
||||
Uint32
|
||||
SignalSender::getAliveNode() const{
|
||||
return theFacade->get_an_alive_node();
|
||||
}
|
||||
|
||||
const ClusterMgr::Node &
|
||||
SignalSender::getNodeInfo(Uint16 nodeId) const {
|
||||
return theFacade->theClusterMgr->getNodeInfo(nodeId);
|
||||
}
|
||||
|
||||
Uint32
|
||||
SignalSender::getNoOfConnectedNodes() const {
|
||||
return theFacade->theClusterMgr->getNoOfConnectedNodes();
|
||||
}
|
||||
|
||||
SendStatus
|
||||
SignalSender::sendSignal(Uint16 nodeId, const SimpleSignal * s){
|
||||
return theFacade->theTransporterRegistry->prepareSend(&s->header,
|
||||
1, // JBB
|
||||
&s->theData[0],
|
||||
nodeId,
|
||||
&s->ptr[0]);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
SimpleSignal *
|
||||
SignalSender::waitFor(Uint32 timeOutMillis, T & t)
|
||||
{
|
||||
SimpleSignal * s = t.check(m_jobBuffer);
|
||||
if(s != 0){
|
||||
return s;
|
||||
}
|
||||
|
||||
NDB_TICKS now = NdbTick_CurrentMillisecond();
|
||||
NDB_TICKS stop = now + timeOutMillis;
|
||||
Uint32 wait = (timeOutMillis == 0 ? 10 : timeOutMillis);
|
||||
do {
|
||||
NdbCondition_WaitTimeout(m_cond,
|
||||
theFacade->theMutexPtr,
|
||||
wait);
|
||||
|
||||
|
||||
SimpleSignal * s = t.check(m_jobBuffer);
|
||||
if(s != 0){
|
||||
m_usedBuffer.push_back(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
now = NdbTick_CurrentMillisecond();
|
||||
wait = (timeOutMillis == 0 ? 10 : stop - now);
|
||||
} while(stop > now || timeOutMillis == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
class WaitForAny {
|
||||
public:
|
||||
SimpleSignal * check(Vector<SimpleSignal*> & m_jobBuffer){
|
||||
if(m_jobBuffer.size() > 0){
|
||||
SimpleSignal * s = m_jobBuffer[0];
|
||||
m_jobBuffer.erase(0);
|
||||
return s;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
SimpleSignal *
|
||||
SignalSender::waitFor(Uint32 timeOutMillis){
|
||||
|
||||
WaitForAny w;
|
||||
return waitFor(timeOutMillis, w);
|
||||
}
|
||||
|
||||
class WaitForNode {
|
||||
public:
|
||||
Uint32 m_nodeId;
|
||||
SimpleSignal * check(Vector<SimpleSignal*> & m_jobBuffer){
|
||||
Uint32 len = m_jobBuffer.size();
|
||||
for(Uint32 i = 0; i<len; i++){
|
||||
if(refToNode(m_jobBuffer[i]->header.theSendersBlockRef) == m_nodeId){
|
||||
SimpleSignal * s = m_jobBuffer[i];
|
||||
m_jobBuffer.erase(i);
|
||||
return s;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
SimpleSignal *
|
||||
SignalSender::waitFor(Uint16 nodeId, Uint32 timeOutMillis){
|
||||
|
||||
WaitForNode w;
|
||||
w.m_nodeId = nodeId;
|
||||
return waitFor(timeOutMillis, w);
|
||||
}
|
||||
|
||||
#include <NdbApiSignal.hpp>
|
||||
|
||||
void
|
||||
SignalSender::execSignal(void* signalSender,
|
||||
NdbApiSignal* signal,
|
||||
class LinearSectionPtr ptr[3]){
|
||||
SimpleSignal * s = new SimpleSignal(true);
|
||||
s->header = * signal;
|
||||
memcpy(&s->theData[0], signal->getDataPtr(), 4 * s->header.theLength);
|
||||
for(Uint32 i = 0; i<s->header.m_noOfSections; i++){
|
||||
s->ptr[i].p = new Uint32[ptr[i].sz];
|
||||
s->ptr[i].sz = ptr[i].sz;
|
||||
memcpy(s->ptr[i].p, ptr[i].p, 4 * ptr[i].sz);
|
||||
}
|
||||
SignalSender * ss = (SignalSender*)signalSender;
|
||||
ss->m_jobBuffer.push_back(s);
|
||||
NdbCondition_Signal(ss->m_cond);
|
||||
}
|
||||
|
||||
void
|
||||
SignalSender::execNodeStatus(void* signalSender,
|
||||
Uint32 nodeId,
|
||||
bool alive,
|
||||
bool nfCompleted){
|
||||
if (alive) {
|
||||
// node connected
|
||||
return;
|
||||
}
|
||||
|
||||
SimpleSignal * s = new SimpleSignal(true);
|
||||
SignalSender * ss = (SignalSender*)signalSender;
|
||||
|
||||
// node disconnected
|
||||
if(nfCompleted)
|
||||
{
|
||||
// node shutdown complete
|
||||
s->header.theVerId_signalNumber = GSN_NF_COMPLETEREP;
|
||||
NFCompleteRep *rep = (NFCompleteRep *)s->getDataPtrSend();
|
||||
rep->failedNodeId = nodeId;
|
||||
}
|
||||
else
|
||||
{
|
||||
// node failure
|
||||
s->header.theVerId_signalNumber = GSN_NODE_FAILREP;
|
||||
NodeFailRep *rep = (NodeFailRep *)s->getDataPtrSend();
|
||||
rep->failNo = nodeId;
|
||||
}
|
||||
|
||||
ss->m_jobBuffer.push_back(s);
|
||||
NdbCondition_Signal(ss->m_cond);
|
||||
}
|
||||
|
||||
template SimpleSignal* SignalSender::waitFor<WaitForNode>(unsigned, WaitForNode&);
|
||||
template SimpleSignal* SignalSender::waitFor<WaitForAny>(unsigned, WaitForAny&);
|
||||
template class Vector<SimpleSignal*>;
|
||||
83
ndb/src/ndbapi/SignalSender.hpp
Normal file
83
ndb/src/ndbapi/SignalSender.hpp
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifndef SIGNAL_SENDER_HPP
|
||||
#define SIGNAL_SENDER_HPP
|
||||
|
||||
#include <ndb_global.h>
|
||||
#include "TransporterFacade.hpp"
|
||||
#include <Vector.hpp>
|
||||
|
||||
struct SimpleSignal {
|
||||
public:
|
||||
SimpleSignal(bool dealloc = false);
|
||||
~SimpleSignal();
|
||||
|
||||
void set(class SignalSender&,
|
||||
Uint8 trace, Uint16 recBlock, Uint16 gsn, Uint32 len);
|
||||
|
||||
struct SignalHeader header;
|
||||
Uint32 theData[25];
|
||||
LinearSectionPtr ptr[3];
|
||||
|
||||
int readSignalNumber() {return header.theVerId_signalNumber; }
|
||||
Uint32 *getDataPtrSend() { return theData; }
|
||||
const Uint32 *getDataPtr() const { return theData; }
|
||||
|
||||
void print(FILE * out = stdout);
|
||||
private:
|
||||
bool deallocSections;
|
||||
};
|
||||
|
||||
class SignalSender {
|
||||
public:
|
||||
SignalSender(TransporterFacade *facade);
|
||||
virtual ~SignalSender();
|
||||
|
||||
int lock();
|
||||
int unlock();
|
||||
|
||||
Uint32 getOwnRef() const;
|
||||
Uint32 getAliveNode() const;
|
||||
const ClusterMgr::Node &getNodeInfo(Uint16 nodeId) const;
|
||||
Uint32 getNoOfConnectedNodes() const;
|
||||
|
||||
SendStatus sendSignal(Uint16 nodeId, const SimpleSignal *);
|
||||
|
||||
SimpleSignal * waitFor(Uint32 timeOutMillis = 0);
|
||||
SimpleSignal * waitFor(Uint16 nodeId, Uint32 timeOutMillis = 0);
|
||||
SimpleSignal * waitFor(Uint16 nodeId, Uint16 gsn, Uint32 timeOutMillis = 0);
|
||||
private:
|
||||
int m_blockNo;
|
||||
TransporterFacade * theFacade;
|
||||
|
||||
static void execSignal(void* signalSender,
|
||||
NdbApiSignal* signal,
|
||||
class LinearSectionPtr ptr[3]);
|
||||
|
||||
static void execNodeStatus(void* signalSender, Uint32 nodeId,
|
||||
bool alive, bool nfCompleted);
|
||||
|
||||
int m_lock;
|
||||
struct NdbCondition * m_cond;
|
||||
Vector<SimpleSignal *> m_jobBuffer;
|
||||
Vector<SimpleSignal *> m_usedBuffer;
|
||||
|
||||
template<class T>
|
||||
SimpleSignal * waitFor(Uint32 timeOutMillis, T & t);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -652,7 +652,8 @@ int ha_tina::rnd_init(bool scan)
|
|||
records= 0;
|
||||
chain_ptr= chain;
|
||||
#ifdef HAVE_MADVISE
|
||||
(void)madvise(share->mapped_file,share->file_stat.st_size,MADV_SEQUENTIAL);
|
||||
if (scan)
|
||||
(void)madvise(share->mapped_file,share->file_stat.st_size,MADV_SEQUENTIAL);
|
||||
#endif
|
||||
|
||||
DBUG_RETURN(0);
|
||||
|
|
|
|||
|
|
@ -632,12 +632,20 @@ int ha_prepare(THD *thd)
|
|||
{
|
||||
int err;
|
||||
statistic_increment(thd->status_var.ha_prepare_count,&LOCK_status);
|
||||
if ((err= (*(*ht)->prepare)(thd, all)))
|
||||
if ((*ht)->prepare)
|
||||
{
|
||||
my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
|
||||
ha_rollback_trans(thd, all);
|
||||
error=1;
|
||||
break;
|
||||
if ((err= (*(*ht)->prepare)(thd, all)))
|
||||
{
|
||||
my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
|
||||
ha_rollback_trans(thd, all);
|
||||
error=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA), (*ht)->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
35
sql/item.cc
35
sql/item.cc
|
|
@ -818,8 +818,25 @@ String *Item_splocal::val_str(String *sp)
|
|||
DBUG_ASSERT(fixed);
|
||||
Item *it= this_item();
|
||||
String *ret= it->val_str(sp);
|
||||
/*
|
||||
This way we mark returned value of val_str as const,
|
||||
so that various functions (e.g. CONCAT) won't try to
|
||||
modify the value of the Item. Analogous mechanism is
|
||||
implemented for Item_param.
|
||||
Without this trick Item_splocal could be changed as a
|
||||
side-effect of expression computation. Here is an example
|
||||
of what happens without it: suppose x is varchar local
|
||||
variable in a SP with initial value 'ab' Then
|
||||
select concat(x,'c');
|
||||
would change x's value to 'abc', as Item_func_concat::val_str()
|
||||
would use x's internal buffer to compute the result.
|
||||
This is intended behaviour of Item_func_concat. Comments to
|
||||
Item_param class contain some more details on the topic.
|
||||
*/
|
||||
str_value_ptr.set(ret->ptr(), ret->length(),
|
||||
ret->charset());
|
||||
null_value= it->null_value;
|
||||
return ret;
|
||||
return &str_value_ptr;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1022,9 +1039,9 @@ void Item::split_sum_func2(THD *thd, Item **ref_pointer_array,
|
|||
/* Will split complicated items and ignore simple ones */
|
||||
split_sum_func(thd, ref_pointer_array, fields);
|
||||
}
|
||||
else if ((type() == SUM_FUNC_ITEM ||
|
||||
(used_tables() & ~PARAM_TABLE_BIT)) &&
|
||||
type() != REF_ITEM)
|
||||
else if ((type() == SUM_FUNC_ITEM || (used_tables() & ~PARAM_TABLE_BIT)) &&
|
||||
(type() != REF_ITEM ||
|
||||
((Item_ref*)this)->ref_type() == Item_ref::VIEW_REF))
|
||||
{
|
||||
/*
|
||||
Replace item with a reference so that we can easily calculate
|
||||
|
|
@ -1033,15 +1050,17 @@ void Item::split_sum_func2(THD *thd, Item **ref_pointer_array,
|
|||
The test above is to ensure we don't do a reference for things
|
||||
that are constants (PARAM_TABLE_BIT is in effect a constant)
|
||||
or already referenced (for example an item in HAVING)
|
||||
Exception is Item_direct_view_ref which we need to convert to
|
||||
Item_ref to allow fields from view being stored in tmp table.
|
||||
*/
|
||||
uint el= fields.elements;
|
||||
Item *new_item;
|
||||
ref_pointer_array[el]= this;
|
||||
Item *new_item, *real_itm= real_item();
|
||||
|
||||
ref_pointer_array[el]= real_itm;
|
||||
if (!(new_item= new Item_ref(&thd->lex->current_select->context,
|
||||
ref_pointer_array + el, 0, name)))
|
||||
return; // fatal_error is set
|
||||
fields.push_front(this);
|
||||
ref_pointer_array[el]= this;
|
||||
fields.push_front(real_itm);
|
||||
thd->change_item_tree(ref, new_item);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
12
sql/item.h
12
sql/item.h
|
|
@ -715,9 +715,17 @@ public:
|
|||
class Item_splocal : public Item
|
||||
{
|
||||
uint m_offset;
|
||||
|
||||
public:
|
||||
LEX_STRING m_name;
|
||||
|
||||
/*
|
||||
Buffer, pointing to the string value of the item. We need it to
|
||||
protect internal buffer from changes. See comment to analogous
|
||||
member in Item_param for more details.
|
||||
*/
|
||||
String str_value_ptr;
|
||||
|
||||
/*
|
||||
Position of this reference to SP variable in the statement (the
|
||||
statement itself is in sp_instr_stmt::m_query).
|
||||
|
|
@ -1537,6 +1545,7 @@ class Item_ref :public Item_ident
|
|||
protected:
|
||||
void set_properties();
|
||||
public:
|
||||
enum Ref_Type { REF, DIRECT_REF, VIEW_REF };
|
||||
Field *result_field; /* Save result here */
|
||||
Item **ref;
|
||||
Item_ref(Name_resolution_context *context_arg,
|
||||
|
|
@ -1617,6 +1626,7 @@ public:
|
|||
void cleanup();
|
||||
Item_field *filed_for_view_update()
|
||||
{ return (*ref)->filed_for_view_update(); }
|
||||
virtual Ref_Type ref_type() { return REF; }
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -1641,6 +1651,7 @@ public:
|
|||
bool val_bool();
|
||||
bool is_null();
|
||||
bool get_date(TIME *ltime,uint fuzzydate);
|
||||
virtual Ref_Type ref_type() { return DIRECT_REF; }
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -1660,6 +1671,7 @@ public:
|
|||
|
||||
bool fix_fields(THD *, Item **);
|
||||
bool eq(const Item *item, bool binary_cmp) const;
|
||||
virtual Ref_Type ref_type() { return VIEW_REF; }
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -988,6 +988,53 @@ longlong Item_func_interval::val_int()
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
Perform context analysis of a BETWEEN item tree
|
||||
|
||||
SYNOPSIS:
|
||||
fix_fields()
|
||||
thd reference to the global context of the query thread
|
||||
tables list of all open tables involved in the query
|
||||
ref pointer to Item* variable where pointer to resulting "fixed"
|
||||
item is to be assigned
|
||||
|
||||
DESCRIPTION
|
||||
This function performs context analysis (name resolution) and calculates
|
||||
various attributes of the item tree with Item_func_between as its root.
|
||||
The function saves in ref the pointer to the item or to a newly created
|
||||
item that is considered as a replacement for the original one.
|
||||
|
||||
NOTES
|
||||
Let T0(e)/T1(e) be the value of not_null_tables(e) when e is used on
|
||||
a predicate/function level. Then it's easy to show that:
|
||||
T0(e BETWEEN e1 AND e2) = union(T1(e),T1(e1),T1(e2))
|
||||
T1(e BETWEEN e1 AND e2) = union(T1(e),intersection(T1(e1),T1(e2)))
|
||||
T0(e NOT BETWEEN e1 AND e2) = union(T1(e),intersection(T1(e1),T1(e2)))
|
||||
T1(e NOT BETWEEN e1 AND e2) = union(T1(e),intersection(T1(e1),T1(e2)))
|
||||
|
||||
RETURN
|
||||
0 ok
|
||||
1 got error
|
||||
*/
|
||||
|
||||
bool
|
||||
Item_func_between::fix_fields(THD *thd, Item **ref)
|
||||
{
|
||||
if (Item_func_opt_neg::fix_fields(thd, ref))
|
||||
return 1;
|
||||
|
||||
/* not_null_tables_cache == union(T1(e),T1(e1),T1(e2)) */
|
||||
if (pred_level && !negated)
|
||||
return 0;
|
||||
|
||||
/* not_null_tables_cache == union(T1(e), intersection(T1(e1),T1(e2))) */
|
||||
not_null_tables_cache= args[0]->not_null_tables() |
|
||||
(args[1]->not_null_tables() & args[2]->not_null_tables());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void Item_func_between::fix_length_and_dec()
|
||||
{
|
||||
max_length= 1;
|
||||
|
|
@ -1040,8 +1087,9 @@ longlong Item_func_between::val_int()
|
|||
a=args[1]->val_str(&value1);
|
||||
b=args[2]->val_str(&value2);
|
||||
if (!args[1]->null_value && !args[2]->null_value)
|
||||
return (sortcmp(value,a,cmp_collation.collation) >= 0 &&
|
||||
sortcmp(value,b,cmp_collation.collation) <= 0) ? 1 : 0;
|
||||
return (longlong) ((sortcmp(value,a,cmp_collation.collation) >= 0 &&
|
||||
sortcmp(value,b,cmp_collation.collation) <= 0) !=
|
||||
negated);
|
||||
if (args[1]->null_value && args[2]->null_value)
|
||||
null_value=1;
|
||||
else if (args[1]->null_value)
|
||||
|
|
@ -1063,7 +1111,7 @@ longlong Item_func_between::val_int()
|
|||
a=args[1]->val_int();
|
||||
b=args[2]->val_int();
|
||||
if (!args[1]->null_value && !args[2]->null_value)
|
||||
return (value >= a && value <= b) ? 1 : 0;
|
||||
return (longlong) ((value >= a && value <= b) != negated);
|
||||
if (args[1]->null_value && args[2]->null_value)
|
||||
null_value=1;
|
||||
else if (args[1]->null_value)
|
||||
|
|
@ -1084,8 +1132,8 @@ longlong Item_func_between::val_int()
|
|||
a_dec= args[1]->val_decimal(&a_buf);
|
||||
b_dec= args[2]->val_decimal(&b_buf);
|
||||
if (!args[1]->null_value && !args[2]->null_value)
|
||||
return (my_decimal_cmp(dec, a_dec)>=0) && (my_decimal_cmp(dec, b_dec)<=0);
|
||||
|
||||
return (longlong) ((my_decimal_cmp(dec, a_dec) >= 0 &&
|
||||
my_decimal_cmp(dec, b_dec) <= 0) != negated);
|
||||
if (args[1]->null_value && args[2]->null_value)
|
||||
null_value=1;
|
||||
else if (args[1]->null_value)
|
||||
|
|
@ -1101,7 +1149,7 @@ longlong Item_func_between::val_int()
|
|||
a= args[1]->val_real();
|
||||
b= args[2]->val_real();
|
||||
if (!args[1]->null_value && !args[2]->null_value)
|
||||
return (value >= a && value <= b) ? 1 : 0;
|
||||
return (longlong) ((value >= a && value <= b) != negated);
|
||||
if (args[1]->null_value && args[2]->null_value)
|
||||
null_value=1;
|
||||
else if (args[1]->null_value)
|
||||
|
|
@ -1113,7 +1161,7 @@ longlong Item_func_between::val_int()
|
|||
null_value= value >= a;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return (longlong) (!null_value && negated);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1244,6 +1292,49 @@ Item_func_ifnull::str_op(String *str)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
Perform context analysis of an IF item tree
|
||||
|
||||
SYNOPSIS:
|
||||
fix_fields()
|
||||
thd reference to the global context of the query thread
|
||||
tables list of all open tables involved in the query
|
||||
ref pointer to Item* variable where pointer to resulting "fixed"
|
||||
item is to be assigned
|
||||
|
||||
DESCRIPTION
|
||||
This function performs context analysis (name resolution) and calculates
|
||||
various attributes of the item tree with Item_func_if as its root.
|
||||
The function saves in ref the pointer to the item or to a newly created
|
||||
item that is considered as a replacement for the original one.
|
||||
|
||||
NOTES
|
||||
Let T0(e)/T1(e) be the value of not_null_tables(e) when e is used on
|
||||
a predicate/function level. Then it's easy to show that:
|
||||
T0(IF(e,e1,e2) = T1(IF(e,e1,e2))
|
||||
T1(IF(e,e1,e2)) = intersection(T1(e1),T1(e2))
|
||||
|
||||
RETURN
|
||||
0 ok
|
||||
1 got error
|
||||
*/
|
||||
|
||||
bool
|
||||
Item_func_if::fix_fields(THD *thd, Item **ref)
|
||||
{
|
||||
DBUG_ASSERT(fixed == 0);
|
||||
args[0]->top_level_item();
|
||||
|
||||
if (Item_func::fix_fields(thd, ref))
|
||||
return 1;
|
||||
|
||||
not_null_tables_cache= (args[1]->not_null_tables()
|
||||
& args[2]->not_null_tables());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Item_func_if::fix_length_and_dec()
|
||||
{
|
||||
|
|
@ -2184,6 +2275,56 @@ bool Item_func_in::nulls_in_row()
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
Perform context analysis of an IN item tree
|
||||
|
||||
SYNOPSIS:
|
||||
fix_fields()
|
||||
thd reference to the global context of the query thread
|
||||
tables list of all open tables involved in the query
|
||||
ref pointer to Item* variable where pointer to resulting "fixed"
|
||||
item is to be assigned
|
||||
|
||||
DESCRIPTION
|
||||
This function performs context analysis (name resolution) and calculates
|
||||
various attributes of the item tree with Item_func_in as its root.
|
||||
The function saves in ref the pointer to the item or to a newly created
|
||||
item that is considered as a replacement for the original one.
|
||||
|
||||
NOTES
|
||||
Let T0(e)/T1(e) be the value of not_null_tables(e) when e is used on
|
||||
a predicate/function level. Then it's easy to show that:
|
||||
T0(e IN(e1,...,en)) = union(T1(e),intersection(T1(ei)))
|
||||
T1(e IN(e1,...,en)) = union(T1(e),intersection(T1(ei)))
|
||||
T0(e NOT IN(e1,...,en)) = union(T1(e),union(T1(ei)))
|
||||
T1(e NOT IN(e1,...,en)) = union(T1(e),intersection(T1(ei)))
|
||||
|
||||
RETURN
|
||||
0 ok
|
||||
1 got error
|
||||
*/
|
||||
|
||||
bool
|
||||
Item_func_in::fix_fields(THD *thd, Item **ref)
|
||||
{
|
||||
Item **arg, **arg_end;
|
||||
|
||||
if (Item_func_opt_neg::fix_fields(thd, ref))
|
||||
return 1;
|
||||
|
||||
/* not_null_tables_cache == union(T1(e),union(T1(ei))) */
|
||||
if (pred_level && negated)
|
||||
return 0;
|
||||
|
||||
/* not_null_tables_cache = union(T1(e),intersection(T1(ei))) */
|
||||
not_null_tables_cache= ~(table_map) 0;
|
||||
for (arg= args + 1, arg_end= args + arg_count; arg != arg_end; arg++)
|
||||
not_null_tables_cache&= (*arg)->not_null_tables();
|
||||
not_null_tables_cache|= (*args)->not_null_tables();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int srtcmp_in(CHARSET_INFO *cs, const String *x,const String *y)
|
||||
{
|
||||
return cs->coll->strnncollsp(cs,
|
||||
|
|
@ -2283,7 +2424,7 @@ longlong Item_func_in::val_int()
|
|||
{
|
||||
int tmp=array->find(args[0]);
|
||||
null_value=args[0]->null_value || (!tmp && have_null);
|
||||
return tmp;
|
||||
return (longlong) (!null_value && tmp != negated);
|
||||
}
|
||||
in_item->store_value(args[0]);
|
||||
if ((null_value=args[0]->null_value))
|
||||
|
|
@ -2292,11 +2433,11 @@ longlong Item_func_in::val_int()
|
|||
for (uint i=1 ; i < arg_count ; i++)
|
||||
{
|
||||
if (!in_item->cmp(args[i]) && !args[i]->null_value)
|
||||
return 1; // Would maybe be nice with i ?
|
||||
return (longlong) (!negated);
|
||||
have_null|= args[i]->null_value;
|
||||
}
|
||||
null_value= have_null;
|
||||
return 0;
|
||||
return (longlong) (!null_value && negated);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -2811,7 +2952,42 @@ bool Item_func_like::fix_fields(THD *thd, Item **ref)
|
|||
{
|
||||
/* If we are on execution stage */
|
||||
String *escape_str= escape_item->val_str(&tmp_value1);
|
||||
escape= escape_str ? *(escape_str->ptr()) : '\\';
|
||||
if (escape_str)
|
||||
{
|
||||
CHARSET_INFO *cs= cmp.cmp_collation.collation;
|
||||
if (use_mb(cs))
|
||||
{
|
||||
my_wc_t wc;
|
||||
int rc= cs->cset->mb_wc(cs, &wc,
|
||||
(const uchar*) escape_str->ptr(),
|
||||
(const uchar*) escape_str->ptr() +
|
||||
escape_str->length());
|
||||
escape= (int) (rc > 0 ? wc : '\\');
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
In the case of 8bit character set, we pass native
|
||||
code instead of Unicode code as "escape" argument.
|
||||
Convert to "cs" if charset of escape differs.
|
||||
*/
|
||||
uint32 unused;
|
||||
if (escape_str->needs_conversion(escape_str->length(),
|
||||
escape_str->charset(), cs, &unused))
|
||||
{
|
||||
char ch;
|
||||
uint errors;
|
||||
uint32 cnvlen= copy_and_convert(&ch, 1, cs, escape_str->ptr(),
|
||||
escape_str->length(),
|
||||
escape_str->charset(), &errors);
|
||||
escape= cnvlen ? ch : '\\';
|
||||
}
|
||||
else
|
||||
escape= *(escape_str->ptr());
|
||||
}
|
||||
}
|
||||
else
|
||||
escape= '\\';
|
||||
|
||||
/*
|
||||
We could also do boyer-more for non-const items, but as we would have to
|
||||
|
|
|
|||
|
|
@ -401,17 +401,49 @@ public:
|
|||
};
|
||||
|
||||
|
||||
class Item_func_between :public Item_int_func
|
||||
/*
|
||||
The class Item_func_opt_neg is defined to factor out the functionality
|
||||
common for the classes Item_func_between and Item_func_in. The objects
|
||||
of these classes can express predicates or there negations.
|
||||
The alternative approach would be to create pairs Item_func_between,
|
||||
Item_func_notbetween and Item_func_in, Item_func_notin.
|
||||
|
||||
*/
|
||||
|
||||
class Item_func_opt_neg :public Item_int_func
|
||||
{
|
||||
public:
|
||||
bool negated; /* <=> the item represents NOT <func> */
|
||||
bool pred_level; /* <=> [NOT] <func> is used on a predicate level */
|
||||
public:
|
||||
Item_func_opt_neg(Item *a, Item *b, Item *c)
|
||||
:Item_int_func(a, b, c), negated(0), pred_level(0) {}
|
||||
Item_func_opt_neg(List<Item> &list)
|
||||
:Item_int_func(list), negated(0), pred_level(0) {}
|
||||
public:
|
||||
inline void negate() { negated= !negated; }
|
||||
inline void top_level_item() { pred_level= 1; }
|
||||
Item *neg_transformer(THD *thd)
|
||||
{
|
||||
negated= !negated;
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class Item_func_between :public Item_func_opt_neg
|
||||
{
|
||||
DTCollation cmp_collation;
|
||||
public:
|
||||
Item_result cmp_type;
|
||||
String value0,value1,value2;
|
||||
Item_func_between(Item *a,Item *b,Item *c) :Item_int_func(a,b,c) {}
|
||||
Item_func_between(Item *a, Item *b, Item *c)
|
||||
:Item_func_opt_neg(a, b, c) {}
|
||||
longlong val_int();
|
||||
optimize_type select_optimize() const { return OPTIMIZE_KEY; }
|
||||
enum Functype functype() const { return BETWEEN; }
|
||||
const char *func_name() const { return "between"; }
|
||||
bool fix_fields(THD *, Item **);
|
||||
void fix_length_and_dec();
|
||||
void print(String *str);
|
||||
bool is_bool_func() { return 1; }
|
||||
|
|
@ -505,16 +537,10 @@ public:
|
|||
String *val_str(String *str);
|
||||
my_decimal *val_decimal(my_decimal *);
|
||||
enum Item_result result_type () const { return cached_result_type; }
|
||||
bool fix_fields(THD *thd, Item **ref)
|
||||
{
|
||||
DBUG_ASSERT(fixed == 0);
|
||||
args[0]->top_level_item();
|
||||
return Item_func::fix_fields(thd, ref);
|
||||
}
|
||||
bool fix_fields(THD *, Item **);
|
||||
void fix_length_and_dec();
|
||||
uint decimal_precision() const;
|
||||
const char *func_name() const { return "if"; }
|
||||
table_map not_null_tables() const { return 0; }
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -819,7 +845,7 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class Item_func_in :public Item_int_func
|
||||
class Item_func_in :public Item_func_opt_neg
|
||||
{
|
||||
Item_result cmp_type;
|
||||
in_vector *array;
|
||||
|
|
@ -828,11 +854,12 @@ class Item_func_in :public Item_int_func
|
|||
DTCollation cmp_collation;
|
||||
public:
|
||||
Item_func_in(List<Item> &list)
|
||||
:Item_int_func(list), array(0), in_item(0), have_null(0)
|
||||
:Item_func_opt_neg(list), array(0), in_item(0), have_null(0)
|
||||
{
|
||||
allowed_arg_cols= 0; // Fetch this value from first argument
|
||||
}
|
||||
longlong val_int();
|
||||
bool fix_fields(THD *, Item **);
|
||||
void fix_length_and_dec();
|
||||
uint decimal_precision() const { return 1; }
|
||||
void cleanup()
|
||||
|
|
@ -853,12 +880,6 @@ class Item_func_in :public Item_int_func
|
|||
bool nulls_in_row();
|
||||
bool is_bool_func() { return 1; }
|
||||
CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
|
||||
/*
|
||||
IN() protect from NULL only first argument, if construction like
|
||||
"expression IN ()" will be allowed, we will need to check number of
|
||||
argument here, because "NOT(NULL IN ())" is TRUE.
|
||||
*/
|
||||
table_map not_null_tables() const { return args[0]->not_null_tables(); }
|
||||
};
|
||||
|
||||
/* Functions used by where clause */
|
||||
|
|
@ -889,7 +910,7 @@ public:
|
|||
else
|
||||
{
|
||||
args[0]->update_used_tables();
|
||||
if (!(used_tables_cache=args[0]->used_tables()))
|
||||
if ((const_item_cache= !(used_tables_cache= args[0]->used_tables())))
|
||||
{
|
||||
/* Remember if the value is always NULL or never NULL */
|
||||
cached_value= (longlong) args[0]->is_null();
|
||||
|
|
@ -966,7 +987,7 @@ class Item_func_like :public Item_bool_func2
|
|||
Item *escape_item;
|
||||
|
||||
public:
|
||||
char escape;
|
||||
int escape;
|
||||
|
||||
Item_func_like(Item *a,Item *b, Item *escape_arg)
|
||||
:Item_bool_func2(a,b), canDoTurboBM(FALSE), pattern(0), pattern_len(0),
|
||||
|
|
|
|||
|
|
@ -3884,7 +3884,8 @@ int get_var_with_binlog(THD *thd, enum_sql_command sql_command,
|
|||
if (!(var_entry= get_variable(&thd->user_vars, name, 0)))
|
||||
goto err;
|
||||
}
|
||||
else if (var_entry->used_query_id == thd->query_id)
|
||||
else if (var_entry->used_query_id == thd->query_id ||
|
||||
mysql_bin_log.is_query_in_union(thd, var_entry->used_query_id))
|
||||
{
|
||||
/*
|
||||
If this variable was already stored in user_var_events by this query
|
||||
|
|
@ -3901,10 +3902,16 @@ int get_var_with_binlog(THD *thd, enum_sql_command sql_command,
|
|||
appears:
|
||||
> set @a:=1;
|
||||
> insert into t1 values (@a), (@a:=@a+1), (@a:=@a+1);
|
||||
We have to write to binlog value @a= 1;
|
||||
We have to write to binlog value @a= 1.
|
||||
|
||||
We allocate the user_var_event on user_var_events_alloc pool, not on
|
||||
the this-statement-execution pool because in SPs user_var_event objects
|
||||
may need to be valid after current [SP] statement execution pool is
|
||||
destroyed.
|
||||
*/
|
||||
size= ALIGN_SIZE(sizeof(BINLOG_USER_VAR_EVENT)) + var_entry->length;
|
||||
if (!(user_var_event= (BINLOG_USER_VAR_EVENT *) thd->alloc(size)))
|
||||
size= ALIGN_SIZE(sizeof(BINLOG_USER_VAR_EVENT)) + var_entry->length;
|
||||
if (!(user_var_event= (BINLOG_USER_VAR_EVENT *)
|
||||
alloc_root(thd->user_var_events_alloc, size)))
|
||||
goto err;
|
||||
|
||||
user_var_event->value= (char*) user_var_event +
|
||||
|
|
|
|||
|
|
@ -2740,7 +2740,9 @@ int dump_leaf_key(byte* key, element_count count __attribute__((unused)),
|
|||
String *result= &item->result;
|
||||
Item **arg= item->args, **arg_end= item->args + item->arg_count_field;
|
||||
|
||||
if (result->length())
|
||||
if (item->no_appended)
|
||||
item->no_appended= FALSE;
|
||||
else
|
||||
result->append(*item->separator);
|
||||
|
||||
tmp.length(0);
|
||||
|
|
@ -2925,6 +2927,7 @@ void Item_func_group_concat::clear()
|
|||
result.copy();
|
||||
null_value= TRUE;
|
||||
warning_for_row= FALSE;
|
||||
no_appended= TRUE;
|
||||
if (tree)
|
||||
reset_tree(tree);
|
||||
/* No need to reset the table as we never call write_row */
|
||||
|
|
@ -3001,6 +3004,7 @@ Item_func_group_concat::fix_fields(THD *thd, Item **ref)
|
|||
args, arg_count, MY_COLL_ALLOW_CONV))
|
||||
return 1;
|
||||
|
||||
result.set_charset(collation.collation);
|
||||
result_field= 0;
|
||||
null_value= 1;
|
||||
thd->allow_sum_func= 1;
|
||||
|
|
|
|||
|
|
@ -881,6 +881,7 @@ class Item_func_group_concat : public Item_sum
|
|||
bool distinct;
|
||||
bool warning_for_row;
|
||||
bool always_null;
|
||||
bool no_appended;
|
||||
/*
|
||||
Following is 0 normal object and pointer to original one for copy
|
||||
(to correctly free resources)
|
||||
|
|
@ -912,8 +913,8 @@ public:
|
|||
virtual Item_result result_type () const { return STRING_RESULT; }
|
||||
void clear();
|
||||
bool add();
|
||||
void reset_field() {} // not used
|
||||
void update_field() {} // not used
|
||||
void reset_field() { DBUG_ASSERT(0); } // not used
|
||||
void update_field() { DBUG_ASSERT(0); } // not used
|
||||
bool fix_fields(THD *,Item **);
|
||||
bool setup(THD *thd);
|
||||
void make_unique();
|
||||
|
|
|
|||
|
|
@ -1560,6 +1560,7 @@ void MYSQL_LOG::start_union_events(THD *thd)
|
|||
thd->binlog_evt_union.do_union= TRUE;
|
||||
thd->binlog_evt_union.unioned_events= FALSE;
|
||||
thd->binlog_evt_union.unioned_events_trans= FALSE;
|
||||
thd->binlog_evt_union.first_query_id= thd->query_id;
|
||||
}
|
||||
|
||||
void MYSQL_LOG::stop_union_events(THD *thd)
|
||||
|
|
@ -1568,6 +1569,12 @@ void MYSQL_LOG::stop_union_events(THD *thd)
|
|||
thd->binlog_evt_union.do_union= FALSE;
|
||||
}
|
||||
|
||||
bool MYSQL_LOG::is_query_in_union(THD *thd, query_id_t query_id_param)
|
||||
{
|
||||
return (thd->binlog_evt_union.do_union &&
|
||||
query_id_param >= thd->binlog_evt_union.first_query_id);
|
||||
}
|
||||
|
||||
/*
|
||||
Write an event to the binary log
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -3529,18 +3529,9 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
|
|||
}
|
||||
|
||||
Item_func *cond_func= (Item_func*) cond;
|
||||
if (cond_func->functype() == Item_func::NOT_FUNC)
|
||||
{
|
||||
/* Optimize NOT BETWEEN and NOT IN */
|
||||
Item *arg= cond_func->arguments()[0];
|
||||
if (arg->type() != Item::FUNC_ITEM)
|
||||
DBUG_RETURN(0);
|
||||
cond_func= (Item_func*) arg;
|
||||
if (cond_func->functype() != Item_func::BETWEEN &&
|
||||
cond_func->functype() != Item_func::IN_FUNC)
|
||||
DBUG_RETURN(0);
|
||||
inv= TRUE;
|
||||
}
|
||||
if (cond_func->functype() == Item_func::BETWEEN ||
|
||||
cond_func->functype() == Item_func::IN_FUNC)
|
||||
inv= ((Item_func_opt_neg *) cond_func)->negated;
|
||||
else if (cond_func->select_optimize() == Item_func::OPTIMIZE_NONE)
|
||||
DBUG_RETURN(0);
|
||||
|
||||
|
|
|
|||
|
|
@ -142,11 +142,8 @@ sys_var_long_ptr sys_binlog_cache_size("binlog_cache_size",
|
|||
sys_var_thd_ulong sys_bulk_insert_buff_size("bulk_insert_buffer_size",
|
||||
&SV::bulk_insert_buff_size);
|
||||
sys_var_character_set_server sys_character_set_server("character_set_server");
|
||||
sys_var_str sys_charset_system("character_set_system",
|
||||
sys_check_charset,
|
||||
sys_update_charset,
|
||||
sys_set_default_charset,
|
||||
(char *)my_charset_utf8_general_ci.name);
|
||||
sys_var_const_str sys_charset_system("character_set_system",
|
||||
(char *)my_charset_utf8_general_ci.name);
|
||||
sys_var_character_set_database sys_character_set_database("character_set_database");
|
||||
sys_var_character_set_client sys_character_set_client("character_set_client");
|
||||
sys_var_character_set_connection sys_character_set_connection("character_set_connection");
|
||||
|
|
@ -571,6 +568,7 @@ sys_var *sys_variables[]=
|
|||
&sys_character_set_client,
|
||||
&sys_character_set_connection,
|
||||
&sys_character_set_results,
|
||||
&sys_charset_system,
|
||||
&sys_collation_connection,
|
||||
&sys_collation_database,
|
||||
&sys_collation_server,
|
||||
|
|
@ -1122,27 +1120,6 @@ static void sys_default_ftb_syntax(THD *thd, enum_var_type type)
|
|||
sizeof(ft_boolean_syntax)-1);
|
||||
}
|
||||
|
||||
/*
|
||||
The following 3 functions need to be changed in 4.1 when we allow
|
||||
one to change character sets
|
||||
*/
|
||||
|
||||
static int sys_check_charset(THD *thd, set_var *var)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static bool sys_update_charset(THD *thd, set_var *var)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void sys_set_default_charset(THD *thd, enum_var_type type)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
If one sets the LOW_PRIORIY UPDATES flag, we also must change the
|
||||
|
|
|
|||
|
|
@ -190,6 +190,7 @@ public:
|
|||
return 1;
|
||||
}
|
||||
bool check_default(enum_var_type type) { return 1; }
|
||||
bool is_readonly() const { return 1; }
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -901,7 +902,7 @@ int sql_set_variables(THD *thd, List<set_var_base> *var_list);
|
|||
bool not_all_support_one_shot(List<set_var_base> *var_list);
|
||||
void fix_delay_key_write(THD *thd, enum_var_type type);
|
||||
ulong fix_sql_mode(ulong sql_mode);
|
||||
extern sys_var_str sys_charset_system;
|
||||
extern sys_var_const_str sys_charset_system;
|
||||
extern sys_var_str sys_init_connect;
|
||||
extern sys_var_str sys_init_slave;
|
||||
extern sys_var_thd_time_zone sys_time_zone;
|
||||
|
|
|
|||
|
|
@ -275,8 +275,19 @@ sp_eval_func_item(THD *thd, Item **it_addr, enum enum_field_types type,
|
|||
}
|
||||
DBUG_PRINT("info",("STRING_RESULT: %*s",
|
||||
s->length(), s->c_ptr_quick()));
|
||||
CHARSET_INFO *itcs= it->collation.collation;
|
||||
CREATE_ON_CALLERS_ARENA(it= new(reuse, &rsize) Item_string(itcs),
|
||||
/*
|
||||
Reuse mechanism in sp_eval_func_item() is only employed for assignments
|
||||
to local variables and OUT/INOUT SP parameters repsesented by
|
||||
Item_splocal. Usually we have some expression, which needs
|
||||
to be calculated and stored into the local variable. However in the
|
||||
case if "it" equals to "reuse", there is no "calculation" step. So,
|
||||
no reason to employ reuse mechanism to save variable into itself.
|
||||
*/
|
||||
if (it == reuse)
|
||||
DBUG_RETURN(it);
|
||||
|
||||
CREATE_ON_CALLERS_ARENA(it= new(reuse, &rsize)
|
||||
Item_string(it->collation.collation),
|
||||
use_callers_arena, &backup_arena);
|
||||
/*
|
||||
We have to use special constructor and allocate string
|
||||
|
|
@ -678,10 +689,35 @@ int cmp_splocal_locations(Item_splocal * const *a, Item_splocal * const *b)
|
|||
* If this function invocation is done from a statement that is written
|
||||
into the binary log.
|
||||
* If there were any attempts to write events to the binary log during
|
||||
function execution.
|
||||
function execution (grep for start_union_events and stop_union_events)
|
||||
|
||||
If the answers are No and Yes, we write the function call into the binary
|
||||
log as "DO spfunc(<param1value>, <param2value>, ...)"
|
||||
|
||||
|
||||
4. Miscellaneous issues.
|
||||
|
||||
4.1 User variables.
|
||||
|
||||
When we call mysql_bin_log.write() for an SP statement, thd->user_var_events
|
||||
must hold set<{var_name, value}> pairs for all user variables used during
|
||||
the statement execution.
|
||||
This set is produced by tracking user variable reads during statement
|
||||
execution.
|
||||
|
||||
Fo SPs, this has the following implications:
|
||||
1) thd->user_var_events may contain events from several SP statements and
|
||||
needs to be valid after exection of these statements was finished. In
|
||||
order to achieve that, we
|
||||
* Allocate user_var_events array elements on appropriate mem_root (grep
|
||||
for user_var_events_alloc).
|
||||
* Use is_query_in_union() to determine if user_var_event is created.
|
||||
|
||||
2) We need to empty thd->user_var_events after we have wrote a function
|
||||
call. This is currently done by making
|
||||
reset_dynamic(&thd->user_var_events);
|
||||
calls in several different places. (TODO cosider moving this into
|
||||
mysql_bin_log.write() function)
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -897,6 +933,7 @@ int sp_head::execute(THD *thd)
|
|||
/* Don't change NOW() in FUNCTION or TRIGGER */
|
||||
if (!thd->in_sub_stmt)
|
||||
thd->set_time(); // Make current_time() et al work
|
||||
|
||||
/*
|
||||
We have to set thd->stmt_arena before executing the instruction
|
||||
to store in the instruction free_list all new items, created
|
||||
|
|
@ -904,6 +941,13 @@ int sp_head::execute(THD *thd)
|
|||
items made during other permanent subquery transformations).
|
||||
*/
|
||||
thd->stmt_arena= i;
|
||||
|
||||
/* will binlog this separately */
|
||||
if (thd->prelocked_mode == NON_PRELOCKED) //TODO: change to event union?
|
||||
{
|
||||
thd->user_var_events_alloc= thd->mem_root;
|
||||
}
|
||||
|
||||
ret= i->execute(thd, &ip);
|
||||
|
||||
/*
|
||||
|
|
@ -918,15 +962,6 @@ int sp_head::execute(THD *thd)
|
|||
|
||||
/* we should cleanup free_list and memroot, used by instruction */
|
||||
thd->free_items();
|
||||
/*
|
||||
FIXME: we must free user var events only if the routine is executed
|
||||
in non-prelocked mode and statement-by-statement replication is used.
|
||||
But if we don't free them now, the server crashes because user var
|
||||
events are allocated in execute_mem_root. This is Bug#12637, and when
|
||||
it's fixed, please add if (thd->options & OPTION_BIN_LOG) here.
|
||||
*/
|
||||
if (opt_bin_log)
|
||||
reset_dynamic(&thd->user_var_events);
|
||||
free_root(&execute_mem_root, MYF(0));
|
||||
|
||||
/*
|
||||
|
|
@ -1084,7 +1119,10 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp)
|
|||
binlog_save_options= thd->options;
|
||||
need_binlog_call= mysql_bin_log.is_open() && (thd->options & OPTION_BIN_LOG);
|
||||
if (need_binlog_call)
|
||||
{
|
||||
reset_dynamic(&thd->user_var_events);
|
||||
mysql_bin_log.start_union_events(thd);
|
||||
}
|
||||
|
||||
thd->options&= ~OPTION_BIN_LOG;
|
||||
ret= execute(thd);
|
||||
|
|
@ -1118,6 +1156,7 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp)
|
|||
"Invoked ROUTINE modified a transactional table but MySQL "
|
||||
"failed to reflect this change in the binary log");
|
||||
}
|
||||
reset_dynamic(&thd->user_var_events);
|
||||
}
|
||||
|
||||
if (m_type == TYPE_ENUM_FUNCTION && ret == 0)
|
||||
|
|
@ -1827,17 +1866,6 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp,
|
|||
thd->query_id= next_query_id();
|
||||
VOID(pthread_mutex_unlock(&LOCK_thread_count));
|
||||
|
||||
/*
|
||||
FIXME. Resetting statement (and using it) is not reentrant, thus recursive
|
||||
functions which try to use the same LEX twice will crash server.
|
||||
We should prevent such situations by tracking if LEX is already
|
||||
in use and throwing error about unallowed recursion if needed.
|
||||
OTOH it is nice to allow recursion in cases when LEX is not really
|
||||
used (e.g. in mathematical functions), so such tracking should be
|
||||
implemented at the same time as ability not to store LEX for
|
||||
instruction if it is not really used.
|
||||
*/
|
||||
|
||||
if (thd->prelocked_mode == NON_PRELOCKED)
|
||||
{
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -108,13 +108,14 @@ class sp_head :private Query_arena
|
|||
MEM_ROOT main_mem_root;
|
||||
public:
|
||||
/* Possible values of m_flags */
|
||||
const static int
|
||||
enum {
|
||||
HAS_RETURN= 1, // For FUNCTIONs only: is set if has RETURN
|
||||
IN_SIMPLE_CASE= 2, // Is set if parsing a simple CASE
|
||||
IN_HANDLER= 4, // Is set if the parser is in a handler body
|
||||
MULTI_RESULTS= 8, // Is set if a procedure with SELECT(s)
|
||||
CONTAINS_DYNAMIC_SQL= 16, // Is set if a procedure with PREPARE/EXECUTE
|
||||
IS_INVOKED= 32; // Is set if this sp_head is being used.
|
||||
IS_INVOKED= 32 // Is set if this sp_head is being used.
|
||||
};
|
||||
|
||||
int m_type; // TYPE_ENUM_FUNCTION or TYPE_ENUM_PROCEDURE
|
||||
uint m_flags; // Boolean attributes of a stored routine
|
||||
|
|
|
|||
|
|
@ -2617,6 +2617,8 @@ find_field_in_view(THD *thd, TABLE_LIST *table_list,
|
|||
table_list->alias, name, item_name, (ulong) ref));
|
||||
Field_iterator_view field_it;
|
||||
field_it.set(table_list);
|
||||
Query_arena *arena, backup;
|
||||
|
||||
DBUG_ASSERT(table_list->schema_table_reformed ||
|
||||
(ref != 0 && table_list->view != 0));
|
||||
for (; !field_it.end_of_fields(); field_it.next())
|
||||
|
|
@ -2638,7 +2640,13 @@ find_field_in_view(THD *thd, TABLE_LIST *table_list,
|
|||
name, length))
|
||||
DBUG_RETURN(WRONG_GRANT);
|
||||
#endif
|
||||
// in PS use own arena or data will be freed after prepare
|
||||
if (register_tree_change)
|
||||
arena= thd->activate_stmt_arena_if_needed(&backup);
|
||||
Item *item= field_it.create_item(thd);
|
||||
if (register_tree_change && arena)
|
||||
thd->restore_active_arena(arena, &backup);
|
||||
|
||||
if (!item)
|
||||
DBUG_RETURN(0);
|
||||
/*
|
||||
|
|
@ -2700,6 +2708,8 @@ find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name,
|
|||
field_it(*(table_ref->join_columns));
|
||||
Natural_join_column *nj_col;
|
||||
Field *found_field;
|
||||
Query_arena *arena, backup;
|
||||
|
||||
DBUG_ENTER("find_field_in_natural_join");
|
||||
DBUG_PRINT("enter", ("field name: '%s', ref 0x%lx",
|
||||
name, (ulong) ref));
|
||||
|
|
@ -2728,7 +2738,14 @@ find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name,
|
|||
The found field is a view field, we do as in find_field_in_view()
|
||||
and return a pointer to pointer to the Item of that field.
|
||||
*/
|
||||
if (register_tree_change)
|
||||
arena= thd->activate_stmt_arena_if_needed(&backup);
|
||||
|
||||
Item *item= nj_col->create_item(thd);
|
||||
|
||||
if (register_tree_change && arena)
|
||||
thd->restore_active_arena(arena, &backup);
|
||||
|
||||
if (!item)
|
||||
DBUG_RETURN(NULL);
|
||||
DBUG_ASSERT(nj_col->table_field == NULL);
|
||||
|
|
@ -2882,14 +2899,15 @@ find_field_in_table_ref(THD *thd, TABLE_LIST *table_list,
|
|||
/*
|
||||
Check that the table and database that qualify the current field name
|
||||
are the same as the table we are going to search for the field.
|
||||
This is done differently for NATURAL/USING joins because there we can't
|
||||
simply compare the qualifying table and database names with the ones of
|
||||
This is done differently for NATURAL/USING joins or nested joins that
|
||||
are operands of NATURAL/USING joins because there we can't simply
|
||||
compare the qualifying table and database names with the ones of
|
||||
'table_list' because each field in such a join may originate from a
|
||||
different table.
|
||||
TODO: Ensure that table_name, db_name and tables->db always points to
|
||||
something !
|
||||
*/
|
||||
if (!table_list->is_natural_join &&
|
||||
if (!(table_list->nested_join && table_list->join_columns) &&
|
||||
table_name && table_name[0] &&
|
||||
(my_strcasecmp(table_alias_charset, table_list->alias, table_name) ||
|
||||
(db_name && db_name[0] && table_list->db && table_list->db[0] &&
|
||||
|
|
@ -2904,8 +2922,13 @@ find_field_in_table_ref(THD *thd, TABLE_LIST *table_list,
|
|||
register_tree_change)))
|
||||
*actual_table= table_list;
|
||||
}
|
||||
else if (table_list->is_natural_join)
|
||||
else if (table_list->nested_join && table_list->join_columns)
|
||||
{
|
||||
/*
|
||||
If this is a NATURAL/USING join, or an operand of such join which is a
|
||||
join itself, and the field name is qualified, then search for the field
|
||||
in the operands of the join.
|
||||
*/
|
||||
if (table_name && table_name[0])
|
||||
{
|
||||
/*
|
||||
|
|
@ -2927,7 +2950,9 @@ find_field_in_table_ref(THD *thd, TABLE_LIST *table_list,
|
|||
}
|
||||
/*
|
||||
Non-qualified field, search directly in the result columns of the
|
||||
natural join.
|
||||
natural join. The condition of the outer IF is true for the top-most
|
||||
natural join, thus if the field is not qualified, we will search
|
||||
directly the top-most NATURAL/USING join.
|
||||
*/
|
||||
fld= find_field_in_natural_join(thd, table_list, name, length, ref,
|
||||
/* TIMOUR_TODO: check this with Sanja */
|
||||
|
|
@ -3569,10 +3594,16 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2,
|
|||
if (add_columns && is_created_2)
|
||||
table_ref_2->join_columns->push_back(cur_nj_col_2);
|
||||
|
||||
/* Compare the two columns and check for duplicate common fields. */
|
||||
/*
|
||||
Compare the two columns and check for duplicate common fields.
|
||||
A common field is duplicate either if it was already found in
|
||||
table_ref_2 (then found == TRUE), or if a field in table_ref_2
|
||||
was already matched by some previous field in table_ref_1
|
||||
(then cur_nj_col_2->is_common == TRUE).
|
||||
*/
|
||||
if (!my_strcasecmp(system_charset_info, field_name_1, cur_field_name_2))
|
||||
{
|
||||
if (found)
|
||||
if (found || cur_nj_col_2->is_common)
|
||||
{
|
||||
my_error(ER_NON_UNIQ_ERROR, MYF(0), field_name_1, thd->where);
|
||||
goto err;
|
||||
|
|
|
|||
|
|
@ -377,14 +377,16 @@ void THD::cleanup(void)
|
|||
mysql_ha_flush(this, (TABLE_LIST*) 0,
|
||||
MYSQL_HA_CLOSE_FINAL | MYSQL_HA_FLUSH_ALL);
|
||||
hash_free(&handler_tables_hash);
|
||||
delete_dynamic(&user_var_events);
|
||||
hash_free(&user_vars);
|
||||
close_temporary_tables(this);
|
||||
my_free((char*) variables.time_format, MYF(MY_ALLOW_ZERO_PTR));
|
||||
my_free((char*) variables.date_format, MYF(MY_ALLOW_ZERO_PTR));
|
||||
my_free((char*) variables.datetime_format, MYF(MY_ALLOW_ZERO_PTR));
|
||||
delete_dynamic(&user_var_events);
|
||||
hash_free(&user_vars);
|
||||
|
||||
sp_cache_clear(&sp_proc_cache);
|
||||
sp_cache_clear(&sp_func_cache);
|
||||
|
||||
if (global_read_lock)
|
||||
unlock_global_read_lock(this);
|
||||
if (ull)
|
||||
|
|
@ -424,9 +426,6 @@ THD::~THD()
|
|||
|
||||
ha_close_connection(this);
|
||||
|
||||
sp_cache_clear(&sp_proc_cache);
|
||||
sp_cache_clear(&sp_func_cache);
|
||||
|
||||
DBUG_PRINT("info", ("freeing host"));
|
||||
if (host != my_localhost) // If not pointer to constant
|
||||
safeFree(host);
|
||||
|
|
|
|||
|
|
@ -313,6 +313,7 @@ public:
|
|||
|
||||
void start_union_events(THD *thd);
|
||||
void stop_union_events(THD *thd);
|
||||
bool is_query_in_union(THD *thd, query_id_t query_id_param);
|
||||
|
||||
/*
|
||||
v stands for vector
|
||||
|
|
@ -1312,8 +1313,9 @@ public:
|
|||
/* variables.transaction_isolation is reset to this after each commit */
|
||||
enum_tx_isolation session_tx_isolation;
|
||||
enum_check_fields count_cuted_fields;
|
||||
/* for user variables replication*/
|
||||
DYNAMIC_ARRAY user_var_events;
|
||||
|
||||
DYNAMIC_ARRAY user_var_events; /* For user variables replication */
|
||||
MEM_ROOT *user_var_events_alloc; /* Allocate above array elements here */
|
||||
|
||||
enum killed_state { NOT_KILLED=0, KILL_BAD_DATA=1, KILL_CONNECTION=ER_SERVER_SHUTDOWN, KILL_QUERY=ER_QUERY_INTERRUPTED };
|
||||
killed_state volatile killed;
|
||||
|
|
@ -1375,6 +1377,12 @@ public:
|
|||
mysql_bin_log.start_union_events() call.
|
||||
*/
|
||||
bool unioned_events_trans;
|
||||
|
||||
/*
|
||||
'queries' (actually SP statements) that run under inside this binlog
|
||||
union have thd->query_id >= first_query_id.
|
||||
*/
|
||||
query_id_t first_query_id;
|
||||
} binlog_evt_union;
|
||||
|
||||
THD();
|
||||
|
|
|
|||
|
|
@ -2442,6 +2442,12 @@ mysql_execute_command(THD *thd)
|
|||
{
|
||||
if (lex->describe)
|
||||
{
|
||||
/*
|
||||
We always use select_send for EXPLAIN, even if it's an EXPLAIN
|
||||
for SELECT ... INTO OUTFILE: a user application should be able
|
||||
to prepend EXPLAIN to any query and receive output for it,
|
||||
even if the query itself redirects the output.
|
||||
*/
|
||||
if (!(result= new select_send()))
|
||||
goto error;
|
||||
else
|
||||
|
|
@ -5166,7 +5172,10 @@ void mysql_reset_thd_for_next_command(THD *thd)
|
|||
if (!thd->in_sub_stmt)
|
||||
{
|
||||
if (opt_bin_log)
|
||||
{
|
||||
reset_dynamic(&thd->user_var_events);
|
||||
thd->user_var_events_alloc= thd->mem_root;
|
||||
}
|
||||
thd->clear_error();
|
||||
thd->total_warn_count=0; // Warnings for this query
|
||||
thd->rand_used= 0;
|
||||
|
|
|
|||
|
|
@ -2874,19 +2874,6 @@ add_key_fields(KEY_FIELD **key_fields,uint *and_level,
|
|||
if (cond->type() != Item::FUNC_ITEM)
|
||||
return;
|
||||
Item_func *cond_func= (Item_func*) cond;
|
||||
if (cond_func->functype() == Item_func::NOT_FUNC)
|
||||
{
|
||||
Item *item= cond_func->arguments()[0];
|
||||
/*
|
||||
At this moment all NOT before simple comparison predicates
|
||||
are eliminated. NOT IN and NOT BETWEEN are treated similar
|
||||
IN and BETWEEN respectively.
|
||||
*/
|
||||
if (item->type() == Item::FUNC_ITEM &&
|
||||
((Item_func *) item)->select_optimize() == Item_func::OPTIMIZE_KEY)
|
||||
add_key_fields(key_fields,and_level,item,usable_tables);
|
||||
return;
|
||||
}
|
||||
switch (cond_func->select_optimize()) {
|
||||
case Item_func::OPTIMIZE_NONE:
|
||||
break;
|
||||
|
|
@ -13087,6 +13074,8 @@ void free_underlaid_joins(THD *thd, SELECT_LEX *select)
|
|||
The function replaces occurrences of group by fields in expr
|
||||
by ref objects for these fields unless they are under aggregate
|
||||
functions.
|
||||
The function also corrects value of the the maybe_null attribute
|
||||
for the items of all subexpressions containing group by fields.
|
||||
|
||||
IMPLEMENTATION
|
||||
The function recursively traverses the tree of the expr expression,
|
||||
|
|
@ -13097,6 +13086,9 @@ void free_underlaid_joins(THD *thd, SELECT_LEX *select)
|
|||
This substitution is needed GROUP BY queries with ROLLUP if
|
||||
SELECT list contains expressions over group by attributes.
|
||||
|
||||
TODO: Some functions are not null-preserving. For those functions
|
||||
updating of the maybe_null attribute is an overkill.
|
||||
|
||||
EXAMPLES
|
||||
SELECT a+1 FROM t1 GROUP BY a WITH ROLLUP
|
||||
SELECT SUM(a)+a FROM t1 GROUP BY a WITH ROLLUP
|
||||
|
|
@ -13118,6 +13110,7 @@ static bool change_group_ref(THD *thd, Item_func *expr, ORDER *group_list,
|
|||
arg != arg_end; arg++)
|
||||
{
|
||||
Item *item= *arg;
|
||||
bool arg_changed= FALSE;
|
||||
if (item->type() == Item::FIELD_ITEM || item->type() == Item::REF_ITEM)
|
||||
{
|
||||
ORDER *group_tmp;
|
||||
|
|
@ -13130,15 +13123,20 @@ static bool change_group_ref(THD *thd, Item_func *expr, ORDER *group_list,
|
|||
item->name)))
|
||||
return 1; // fatal_error is set
|
||||
thd->change_item_tree(arg, new_item);
|
||||
*changed= TRUE;
|
||||
arg_changed= TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (item->type() == Item::FUNC_ITEM)
|
||||
{
|
||||
if (change_group_ref(thd, (Item_func *) item, group_list, changed))
|
||||
if (change_group_ref(thd, (Item_func *) item, group_list, &arg_changed))
|
||||
return 1;
|
||||
}
|
||||
if (arg_changed)
|
||||
{
|
||||
expr->maybe_null= 1;
|
||||
*changed= TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -13201,7 +13199,7 @@ bool JOIN::rollup_init()
|
|||
}
|
||||
if (item->type() == Item::FUNC_ITEM)
|
||||
{
|
||||
bool changed= 0;
|
||||
bool changed= FALSE;
|
||||
if (change_group_ref(thd, (Item_func *) item, group_list, &changed))
|
||||
return 1;
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -231,7 +231,7 @@ class JOIN :public Sql_alloc
|
|||
/* Is set if we have a GROUP BY and we have ORDER BY on a constant. */
|
||||
bool skip_sort_order;
|
||||
|
||||
bool need_tmp, hidden_group_fields, buffer_result;
|
||||
bool need_tmp, hidden_group_fields;
|
||||
DYNAMIC_ARRAY keyuse;
|
||||
Item::cond_result cond_value;
|
||||
List<Item> all_fields; // to store all fields that used in query
|
||||
|
|
@ -300,8 +300,6 @@ class JOIN :public Sql_alloc
|
|||
skip_sort_order= 0;
|
||||
need_tmp= 0;
|
||||
hidden_group_fields= 0; /*safety*/
|
||||
buffer_result= test(select_options & OPTION_BUFFER_RESULT) &&
|
||||
!test(select_options & OPTION_FOUND_ROWS);
|
||||
error= 0;
|
||||
select= 0;
|
||||
return_tab= 0;
|
||||
|
|
|
|||
|
|
@ -2010,10 +2010,20 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
|
|||
/*
|
||||
get_all_tables() returns 1 on failure and 0 on success thus
|
||||
return only these and not the result code of ::process_table()
|
||||
|
||||
We should use show_table_list->alias instead of
|
||||
show_table_list->table_name because table_name
|
||||
could be changed during opening of I_S tables. It's safe
|
||||
to use alias because alias contains original table name
|
||||
in this case(this part of code is used only for
|
||||
'show columns' & 'show statistics' commands).
|
||||
*/
|
||||
error= test(schema_table->process_table(thd, show_table_list,
|
||||
table, res, show_table_list->db,
|
||||
show_table_list->alias));
|
||||
table, res,
|
||||
(show_table_list->view ?
|
||||
show_table_list->view_db.str :
|
||||
show_table_list->db),
|
||||
show_table_list->alias));
|
||||
close_thread_tables(thd);
|
||||
show_table_list->table= 0;
|
||||
goto err;
|
||||
|
|
@ -2114,6 +2124,13 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
|
|||
lex->derived_tables= 0;
|
||||
res= open_normal_and_derived_tables(thd, show_table_list,
|
||||
MYSQL_LOCK_IGNORE_FLUSH);
|
||||
/*
|
||||
We should use show_table_list->alias instead of
|
||||
show_table_list->table_name because table_name
|
||||
could be changed during opening of I_S tables. It's safe
|
||||
to use alias because alias contains original table name
|
||||
in this case.
|
||||
*/
|
||||
res= schema_table->process_table(thd, show_table_list, table,
|
||||
res, base_name,
|
||||
show_table_list->alias);
|
||||
|
|
|
|||
|
|
@ -4866,7 +4866,9 @@ predicate:
|
|||
else
|
||||
{
|
||||
$5->push_front($1);
|
||||
$$= negate_expression(YYTHD, new Item_func_in(*$5));
|
||||
Item_func_in *item = new Item_func_in(*$5);
|
||||
item->negate();
|
||||
$$= item;
|
||||
}
|
||||
}
|
||||
| bit_expr IN_SYM in_subselect
|
||||
|
|
@ -4876,7 +4878,11 @@ predicate:
|
|||
| bit_expr BETWEEN_SYM bit_expr AND_SYM predicate
|
||||
{ $$= new Item_func_between($1,$3,$5); }
|
||||
| bit_expr not BETWEEN_SYM bit_expr AND_SYM predicate
|
||||
{ $$= negate_expression(YYTHD, new Item_func_between($1,$4,$6)); }
|
||||
{
|
||||
Item_func_between *item= new Item_func_between($1,$4,$6);
|
||||
item->negate();
|
||||
$$= item;
|
||||
}
|
||||
| bit_expr SOUNDS_SYM LIKE bit_expr
|
||||
{ $$= new Item_func_eq(new Item_func_soundex($1),
|
||||
new Item_func_soundex($4)); }
|
||||
|
|
@ -8755,6 +8761,11 @@ handler:
|
|||
HANDLER_SYM table_ident OPEN_SYM opt_table_alias
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
if (lex->sphead)
|
||||
{
|
||||
my_error(ER_SP_BADSTATEMENT, MYF(0), "HANDLER");
|
||||
YYABORT;
|
||||
}
|
||||
lex->sql_command = SQLCOM_HA_OPEN;
|
||||
if (!lex->current_select->add_table_to_list(lex->thd, $2, $4, 0))
|
||||
YYABORT;
|
||||
|
|
@ -8762,6 +8773,11 @@ handler:
|
|||
| HANDLER_SYM table_ident_nodb CLOSE_SYM
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
if (lex->sphead)
|
||||
{
|
||||
my_error(ER_SP_BADSTATEMENT, MYF(0), "HANDLER");
|
||||
YYABORT;
|
||||
}
|
||||
lex->sql_command = SQLCOM_HA_CLOSE;
|
||||
if (!lex->current_select->add_table_to_list(lex->thd, $2, 0, 0))
|
||||
YYABORT;
|
||||
|
|
@ -8769,6 +8785,11 @@ handler:
|
|||
| HANDLER_SYM table_ident_nodb READ_SYM
|
||||
{
|
||||
LEX *lex=Lex;
|
||||
if (lex->sphead)
|
||||
{
|
||||
my_error(ER_SP_BADSTATEMENT, MYF(0), "HANDLER");
|
||||
YYABORT;
|
||||
}
|
||||
lex->sql_command = SQLCOM_HA_READ;
|
||||
lex->ha_rkey_mode= HA_READ_KEY_EXACT; /* Avoid purify warnings */
|
||||
lex->current_select->select_limit= new Item_int((int32) 1);
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ class DefineBackupReq {
|
|||
|
||||
friend bool printDEFINE_BACKUP_REQ(FILE *, const Uint32 *, Uint32, Uint16);
|
||||
public:
|
||||
STATIC_CONST( SignalLength = 8 + NdbNodeBitmask::Size);
|
||||
STATIC_CONST( SignalLength = 9 + NdbNodeBitmask::Size);
|
||||
|
||||
private:
|
||||
/**
|
||||
|
|
@ -60,6 +60,13 @@ private:
|
|||
* Length of backup data
|
||||
*/
|
||||
Uint32 backupDataLen;
|
||||
|
||||
/**
|
||||
* Backup flags
|
||||
*/
|
||||
/* & 0x3 - waitCompleted
|
||||
*/
|
||||
Uint32 flags;
|
||||
};
|
||||
|
||||
class DefineBackupRef {
|
||||
|
|
|
|||
|
|
@ -36,11 +36,14 @@ class BackupReq {
|
|||
|
||||
friend bool printBACKUP_REQ(FILE *, const Uint32 *, Uint32, Uint16);
|
||||
public:
|
||||
STATIC_CONST( SignalLength = 2 );
|
||||
STATIC_CONST( SignalLength = 3 );
|
||||
|
||||
private:
|
||||
Uint32 senderData;
|
||||
Uint32 backupDataLen;
|
||||
/* & 0x3 - waitCompleted
|
||||
*/
|
||||
Uint32 flags;
|
||||
};
|
||||
|
||||
class BackupData {
|
||||
|
|
|
|||
|
|
@ -30,28 +30,12 @@
|
|||
* from the failed NDB node
|
||||
*
|
||||
*/
|
||||
class NFCompleteRep {
|
||||
/**
|
||||
* Sender(s)
|
||||
*/
|
||||
friend class Dbdict;
|
||||
friend class Dblqh;
|
||||
friend class Dbtc;
|
||||
friend class Qmgr;
|
||||
|
||||
/**
|
||||
* Sender/Reciver
|
||||
*/
|
||||
friend class Dbdih;
|
||||
friend class ClusterMgr;
|
||||
struct NFCompleteRep {
|
||||
|
||||
friend bool printNF_COMPLETE_REP(FILE *, const Uint32 *, Uint32, Uint16);
|
||||
|
||||
public:
|
||||
STATIC_CONST( SignalLength = 5 );
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Which block has completed...
|
||||
*
|
||||
|
|
|
|||
|
|
@ -24,34 +24,8 @@
|
|||
* This signals is sent by Qmgr to NdbCntr
|
||||
* and then from NdbCntr sent to: dih, dict, lqh, tc & API
|
||||
*/
|
||||
class NodeFailRep {
|
||||
/**
|
||||
* Sender(s)
|
||||
*/
|
||||
friend class Qmgr;
|
||||
|
||||
/**
|
||||
* Sender(s) / Reciver(s)
|
||||
*/
|
||||
friend class Ndbcntr;
|
||||
friend class Dbdict;
|
||||
|
||||
/**
|
||||
* Reciver(s)
|
||||
*/
|
||||
friend class Dbdih;
|
||||
friend class Dblqh;
|
||||
friend class Dbtc;
|
||||
friend class ClusterMgr;
|
||||
friend class Trix;
|
||||
friend class Backup;
|
||||
friend class Suma;
|
||||
friend class Grep;
|
||||
friend class SafeCounterManager;
|
||||
|
||||
public:
|
||||
struct NodeFailRep {
|
||||
STATIC_CONST( SignalLength = 3 + NodeBitmask::Size );
|
||||
private:
|
||||
|
||||
Uint32 failNo;
|
||||
|
||||
|
|
|
|||
|
|
@ -69,6 +69,9 @@ static const Uint32 BACKUP_SEQUENCE = 0x1F000000;
|
|||
|
||||
static Uint32 g_TypeOfStart = NodeState::ST_ILLEGAL_TYPE;
|
||||
|
||||
#define SEND_BACKUP_STARTED_FLAG(A) (((A) & 0x3) > 0)
|
||||
#define SEND_BACKUP_COMPLETED_FLAG(A) (((A) & 0x3) > 1)
|
||||
|
||||
void
|
||||
Backup::execSTTOR(Signal* signal)
|
||||
{
|
||||
|
|
@ -852,23 +855,24 @@ Backup::execBACKUP_REQ(Signal* signal)
|
|||
const Uint32 senderData = req->senderData;
|
||||
const BlockReference senderRef = signal->senderBlockRef();
|
||||
const Uint32 dataLen32 = req->backupDataLen; // In 32 bit words
|
||||
|
||||
const Uint32 flags = signal->getLength() > 2 ? req->flags : 2;
|
||||
|
||||
if(getOwnNodeId() != getMasterNodeId()) {
|
||||
jam();
|
||||
sendBackupRef(senderRef, signal, senderData, BackupRef::IAmNotMaster);
|
||||
sendBackupRef(senderRef, flags, signal, senderData, BackupRef::IAmNotMaster);
|
||||
return;
|
||||
}//if
|
||||
|
||||
if (m_diskless)
|
||||
{
|
||||
sendBackupRef(senderRef, signal, senderData,
|
||||
sendBackupRef(senderRef, flags, signal, senderData,
|
||||
BackupRef::CannotBackupDiskless);
|
||||
return;
|
||||
}
|
||||
|
||||
if(dataLen32 != 0) {
|
||||
jam();
|
||||
sendBackupRef(senderRef, signal, senderData,
|
||||
sendBackupRef(senderRef, flags, signal, senderData,
|
||||
BackupRef::BackupDefinitionNotImplemented);
|
||||
return;
|
||||
}//if
|
||||
|
|
@ -883,7 +887,7 @@ Backup::execBACKUP_REQ(Signal* signal)
|
|||
c_backups.seize(ptr);
|
||||
if(ptr.i == RNIL) {
|
||||
jam();
|
||||
sendBackupRef(senderRef, signal, senderData, BackupRef::OutOfBackupRecord);
|
||||
sendBackupRef(senderRef, flags, signal, senderData, BackupRef::OutOfBackupRecord);
|
||||
return;
|
||||
}//if
|
||||
|
||||
|
|
@ -894,6 +898,7 @@ Backup::execBACKUP_REQ(Signal* signal)
|
|||
ptr.p->errorCode = 0;
|
||||
ptr.p->clientRef = senderRef;
|
||||
ptr.p->clientData = senderData;
|
||||
ptr.p->flags = flags;
|
||||
ptr.p->masterRef = reference();
|
||||
ptr.p->nodes = c_aliveNodes;
|
||||
ptr.p->backupId = 0;
|
||||
|
|
@ -931,20 +936,23 @@ void
|
|||
Backup::sendBackupRef(Signal* signal, BackupRecordPtr ptr, Uint32 errorCode)
|
||||
{
|
||||
jam();
|
||||
sendBackupRef(ptr.p->clientRef, signal, ptr.p->clientData, errorCode);
|
||||
sendBackupRef(ptr.p->clientRef, ptr.p->flags, signal, ptr.p->clientData, errorCode);
|
||||
cleanup(signal, ptr);
|
||||
}
|
||||
|
||||
void
|
||||
Backup::sendBackupRef(BlockReference senderRef, Signal *signal,
|
||||
Backup::sendBackupRef(BlockReference senderRef, Uint32 flags, Signal *signal,
|
||||
Uint32 senderData, Uint32 errorCode)
|
||||
{
|
||||
jam();
|
||||
BackupRef* ref = (BackupRef*)signal->getDataPtrSend();
|
||||
ref->senderData = senderData;
|
||||
ref->errorCode = errorCode;
|
||||
ref->masterRef = numberToRef(BACKUP, getMasterNodeId());
|
||||
sendSignal(senderRef, GSN_BACKUP_REF, signal, BackupRef::SignalLength, JBB);
|
||||
if (SEND_BACKUP_STARTED_FLAG(flags))
|
||||
{
|
||||
BackupRef* ref = (BackupRef*)signal->getDataPtrSend();
|
||||
ref->senderData = senderData;
|
||||
ref->errorCode = errorCode;
|
||||
ref->masterRef = numberToRef(BACKUP, getMasterNodeId());
|
||||
sendSignal(senderRef, GSN_BACKUP_REF, signal, BackupRef::SignalLength, JBB);
|
||||
}
|
||||
|
||||
if(errorCode != BackupRef::IAmNotMaster){
|
||||
signal->theData[0] = NDB_LE_BackupFailedToStart;
|
||||
|
|
@ -1098,6 +1106,7 @@ Backup::sendDefineBackupReq(Signal *signal, BackupRecordPtr ptr)
|
|||
req->backupKey[1] = ptr.p->backupKey[1];
|
||||
req->nodes = ptr.p->nodes;
|
||||
req->backupDataLen = ptr.p->backupDataLen;
|
||||
req->flags = ptr.p->flags;
|
||||
|
||||
ptr.p->masterData.gsn = GSN_DEFINE_BACKUP_REQ;
|
||||
ptr.p->masterData.sendCounter = ptr.p->nodes;
|
||||
|
|
@ -1193,13 +1202,18 @@ Backup::defineBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32 nodeId)
|
|||
/**
|
||||
* Reply to client
|
||||
*/
|
||||
BackupConf * conf = (BackupConf*)signal->getDataPtrSend();
|
||||
conf->backupId = ptr.p->backupId;
|
||||
conf->senderData = ptr.p->clientData;
|
||||
conf->nodes = ptr.p->nodes;
|
||||
sendSignal(ptr.p->clientRef, GSN_BACKUP_CONF, signal,
|
||||
BackupConf::SignalLength, JBB);
|
||||
|
||||
CRASH_INSERTION((10034));
|
||||
|
||||
if (SEND_BACKUP_STARTED_FLAG(ptr.p->flags))
|
||||
{
|
||||
BackupConf * conf = (BackupConf*)signal->getDataPtrSend();
|
||||
conf->backupId = ptr.p->backupId;
|
||||
conf->senderData = ptr.p->clientData;
|
||||
conf->nodes = ptr.p->nodes;
|
||||
sendSignal(ptr.p->clientRef, GSN_BACKUP_CONF, signal,
|
||||
BackupConf::SignalLength, JBB);
|
||||
}
|
||||
|
||||
signal->theData[0] = NDB_LE_BackupStarted;
|
||||
signal->theData[1] = ptr.p->clientRef;
|
||||
signal->theData[2] = ptr.p->backupId;
|
||||
|
|
@ -2080,19 +2094,22 @@ Backup::stopBackupReply(Signal* signal, BackupRecordPtr ptr, Uint32 nodeId)
|
|||
|
||||
if(!ptr.p->checkError())
|
||||
{
|
||||
BackupCompleteRep * rep = (BackupCompleteRep*)signal->getDataPtrSend();
|
||||
rep->backupId = ptr.p->backupId;
|
||||
rep->senderData = ptr.p->clientData;
|
||||
rep->startGCP = ptr.p->startGCP;
|
||||
rep->stopGCP = ptr.p->stopGCP;
|
||||
rep->noOfBytes = ptr.p->noOfBytes;
|
||||
rep->noOfRecords = ptr.p->noOfRecords;
|
||||
rep->noOfLogBytes = ptr.p->noOfLogBytes;
|
||||
rep->noOfLogRecords = ptr.p->noOfLogRecords;
|
||||
rep->nodes = ptr.p->nodes;
|
||||
sendSignal(ptr.p->clientRef, GSN_BACKUP_COMPLETE_REP, signal,
|
||||
BackupCompleteRep::SignalLength, JBB);
|
||||
|
||||
if (SEND_BACKUP_COMPLETED_FLAG(ptr.p->flags))
|
||||
{
|
||||
BackupCompleteRep * rep = (BackupCompleteRep*)signal->getDataPtrSend();
|
||||
rep->backupId = ptr.p->backupId;
|
||||
rep->senderData = ptr.p->clientData;
|
||||
rep->startGCP = ptr.p->startGCP;
|
||||
rep->stopGCP = ptr.p->stopGCP;
|
||||
rep->noOfBytes = ptr.p->noOfBytes;
|
||||
rep->noOfRecords = ptr.p->noOfRecords;
|
||||
rep->noOfLogBytes = ptr.p->noOfLogBytes;
|
||||
rep->noOfLogRecords = ptr.p->noOfLogRecords;
|
||||
rep->nodes = ptr.p->nodes;
|
||||
sendSignal(ptr.p->clientRef, GSN_BACKUP_COMPLETE_REP, signal,
|
||||
BackupCompleteRep::SignalLength, JBB);
|
||||
}
|
||||
|
||||
signal->theData[0] = NDB_LE_BackupCompleted;
|
||||
signal->theData[1] = ptr.p->clientRef;
|
||||
signal->theData[2] = ptr.p->backupId;
|
||||
|
|
@ -2129,13 +2146,15 @@ Backup::masterAbort(Signal* signal, BackupRecordPtr ptr)
|
|||
return;
|
||||
}
|
||||
|
||||
BackupAbortRep* rep = (BackupAbortRep*)signal->getDataPtrSend();
|
||||
rep->backupId = ptr.p->backupId;
|
||||
rep->senderData = ptr.p->clientData;
|
||||
rep->reason = ptr.p->errorCode;
|
||||
sendSignal(ptr.p->clientRef, GSN_BACKUP_ABORT_REP, signal,
|
||||
BackupAbortRep::SignalLength, JBB);
|
||||
|
||||
if (SEND_BACKUP_COMPLETED_FLAG(ptr.p->flags))
|
||||
{
|
||||
BackupAbortRep* rep = (BackupAbortRep*)signal->getDataPtrSend();
|
||||
rep->backupId = ptr.p->backupId;
|
||||
rep->senderData = ptr.p->clientData;
|
||||
rep->reason = ptr.p->errorCode;
|
||||
sendSignal(ptr.p->clientRef, GSN_BACKUP_ABORT_REP, signal,
|
||||
BackupAbortRep::SignalLength, JBB);
|
||||
}
|
||||
signal->theData[0] = NDB_LE_BackupAborted;
|
||||
signal->theData[1] = ptr.p->clientRef;
|
||||
signal->theData[2] = ptr.p->backupId;
|
||||
|
|
@ -2267,6 +2286,13 @@ Backup::execDEFINE_BACKUP_REQ(Signal* signal)
|
|||
ptr.p->errorCode = 0;
|
||||
ptr.p->clientRef = req->clientRef;
|
||||
ptr.p->clientData = req->clientData;
|
||||
if(senderRef == reference())
|
||||
ptr.p->flags = req->flags;
|
||||
else
|
||||
ptr.p->flags = req->flags & ~((Uint32)0x3); /* remove waitCompleted flags
|
||||
* as non master should never
|
||||
* reply
|
||||
*/
|
||||
ptr.p->masterRef = senderRef;
|
||||
ptr.p->nodes = req->nodes;
|
||||
ptr.p->backupId = backupId;
|
||||
|
|
|
|||
|
|
@ -412,6 +412,7 @@ public:
|
|||
|
||||
Uint32 clientRef;
|
||||
Uint32 clientData;
|
||||
Uint32 flags;
|
||||
Uint32 backupId;
|
||||
Uint32 backupKey[2];
|
||||
Uint32 masterRef;
|
||||
|
|
@ -592,7 +593,7 @@ public:
|
|||
|
||||
bool insertFileHeader(BackupFormat::FileType, BackupRecord*, BackupFile*);
|
||||
void sendBackupRef(Signal* signal, BackupRecordPtr ptr, Uint32 errorCode);
|
||||
void sendBackupRef(BlockReference ref, Signal *signal,
|
||||
void sendBackupRef(BlockReference ref, Uint32 flags, Signal *signal,
|
||||
Uint32 senderData, Uint32 errorCode);
|
||||
void dumpUsedResources();
|
||||
void cleanup(Signal*, BackupRecordPtr ptr);
|
||||
|
|
|
|||
|
|
@ -410,5 +410,5 @@ handler_sigusr1(int signum)
|
|||
failed_startups++;
|
||||
failed_startup_flag = true;
|
||||
}
|
||||
g_eventLogger.info("Received signal %d. Ndbd failed startup (%u).", signum, failed_startups);
|
||||
g_eventLogger.info("Angel received ndbd startup failure count %u.", failed_startups);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@
|
|||
#include <signaldata/BackupSignalData.hpp>
|
||||
#include <signaldata/GrepImpl.hpp>
|
||||
#include <signaldata/ManagementServer.hpp>
|
||||
#include <signaldata/NFCompleteRep.hpp>
|
||||
#include <signaldata/NodeFailRep.hpp>
|
||||
#include <NdbSleep.h>
|
||||
#include <EventLogger.hpp>
|
||||
#include <DebuggerNames.hpp>
|
||||
|
|
@ -56,6 +58,8 @@
|
|||
#include <mgmapi_config_parameters.h>
|
||||
#include <m_string.h>
|
||||
|
||||
#include <SignalSender.hpp>
|
||||
|
||||
//#define MGM_SRV_DEBUG
|
||||
#ifdef MGM_SRV_DEBUG
|
||||
#define DEBUG(x) do ndbout << x << endl; while(0)
|
||||
|
|
@ -727,6 +731,15 @@ int MgmtSrvr::okToSendTo(NodeId processId, bool unCond)
|
|||
}
|
||||
}
|
||||
|
||||
void report_unknown_signal(SimpleSignal *signal)
|
||||
{
|
||||
g_eventLogger.error("Unknown signal received. SignalNumber: "
|
||||
"%i from (%d, %x)",
|
||||
signal->readSignalNumber(),
|
||||
refToNode(signal->header.theSendersBlockRef),
|
||||
refToBlock(signal->header.theSendersBlockRef));
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Starting and stopping database nodes
|
||||
****************************************************************************/
|
||||
|
|
@ -1927,81 +1940,6 @@ MgmtSrvr::handleReceivedSignal(NdbApiSignal* signal)
|
|||
}
|
||||
break;
|
||||
|
||||
case GSN_BACKUP_CONF:{
|
||||
const BackupConf * const conf =
|
||||
CAST_CONSTPTR(BackupConf, signal->getDataPtr());
|
||||
BackupEvent event;
|
||||
event.Event = BackupEvent::BackupStarted;
|
||||
event.Started.BackupId = conf->backupId;
|
||||
event.Nodes = conf->nodes;
|
||||
#ifdef VM_TRACE
|
||||
ndbout_c("Backup master is %d", refToNode(signal->theSendersBlockRef));
|
||||
#endif
|
||||
backupCallback(event);
|
||||
}
|
||||
break;
|
||||
|
||||
case GSN_BACKUP_REF:{
|
||||
const BackupRef * const ref =
|
||||
CAST_CONSTPTR(BackupRef, signal->getDataPtr());
|
||||
Uint32 errCode = ref->errorCode;
|
||||
if(ref->errorCode == BackupRef::IAmNotMaster){
|
||||
const Uint32 aNodeId = refToNode(ref->masterRef);
|
||||
#ifdef VM_TRACE
|
||||
ndbout_c("I'm not master resending to %d", aNodeId);
|
||||
#endif
|
||||
theWaitNode= aNodeId;
|
||||
NdbApiSignal aSignal(_ownReference);
|
||||
BackupReq* req = CAST_PTR(BackupReq, aSignal.getDataPtrSend());
|
||||
aSignal.set(TestOrd::TraceAPI, BACKUP, GSN_BACKUP_REQ,
|
||||
BackupReq::SignalLength);
|
||||
req->senderData = 19;
|
||||
req->backupDataLen = 0;
|
||||
|
||||
int i = theFacade->sendSignalUnCond(&aSignal, aNodeId);
|
||||
if(i == 0){
|
||||
return;
|
||||
}
|
||||
errCode = 5030;
|
||||
}
|
||||
BackupEvent event;
|
||||
event.Event = BackupEvent::BackupFailedToStart;
|
||||
event.FailedToStart.ErrorCode = errCode;
|
||||
backupCallback(event);
|
||||
break;
|
||||
}
|
||||
|
||||
case GSN_BACKUP_ABORT_REP:{
|
||||
const BackupAbortRep * const rep =
|
||||
CAST_CONSTPTR(BackupAbortRep, signal->getDataPtr());
|
||||
BackupEvent event;
|
||||
event.Event = BackupEvent::BackupAborted;
|
||||
event.Aborted.Reason = rep->reason;
|
||||
event.Aborted.BackupId = rep->backupId;
|
||||
event.Aborted.ErrorCode = rep->reason;
|
||||
backupCallback(event);
|
||||
}
|
||||
break;
|
||||
|
||||
case GSN_BACKUP_COMPLETE_REP:{
|
||||
const BackupCompleteRep * const rep =
|
||||
CAST_CONSTPTR(BackupCompleteRep, signal->getDataPtr());
|
||||
BackupEvent event;
|
||||
event.Event = BackupEvent::BackupCompleted;
|
||||
event.Completed.BackupId = rep->backupId;
|
||||
|
||||
event.Completed.NoOfBytes = rep->noOfBytes;
|
||||
event.Completed.NoOfLogBytes = rep->noOfLogBytes;
|
||||
event.Completed.NoOfRecords = rep->noOfRecords;
|
||||
event.Completed.NoOfLogRecords = rep->noOfLogRecords;
|
||||
event.Completed.stopGCP = rep->stopGCP;
|
||||
event.Completed.startGCP = rep->startGCP;
|
||||
event.Nodes = rep->nodes;
|
||||
|
||||
backupCallback(event);
|
||||
}
|
||||
break;
|
||||
|
||||
case GSN_MGM_LOCK_CONFIG_REP:
|
||||
case GSN_MGM_LOCK_CONFIG_REQ:
|
||||
case GSN_MGM_UNLOCK_CONFIG_REP:
|
||||
|
|
@ -2466,6 +2404,9 @@ MgmtSrvr::eventReport(NodeId nodeId, const Uint32 * theData)
|
|||
int
|
||||
MgmtSrvr::startBackup(Uint32& backupId, int waitCompleted)
|
||||
{
|
||||
SignalSender ss(theFacade);
|
||||
ss.lock(); // lock will be released on exit
|
||||
|
||||
bool next;
|
||||
NodeId nodeId = 0;
|
||||
while((next = getNextNodeId(&nodeId, NDB_MGM_NODE_TYPE_NDB)) == true &&
|
||||
|
|
@ -2473,49 +2414,126 @@ MgmtSrvr::startBackup(Uint32& backupId, int waitCompleted)
|
|||
|
||||
if(!next) return NO_CONTACT_WITH_DB_NODES;
|
||||
|
||||
NdbApiSignal* signal = getSignal();
|
||||
if (signal == NULL) {
|
||||
return COULD_NOT_ALLOCATE_MEMORY;
|
||||
}
|
||||
SimpleSignal ssig;
|
||||
|
||||
BackupReq* req = CAST_PTR(BackupReq, signal->getDataPtrSend());
|
||||
signal->set(TestOrd::TraceAPI, BACKUP, GSN_BACKUP_REQ,
|
||||
BackupReq::SignalLength);
|
||||
BackupReq* req = CAST_PTR(BackupReq, ssig.getDataPtrSend());
|
||||
ssig.set(ss, TestOrd::TraceAPI, BACKUP, GSN_BACKUP_REQ,
|
||||
BackupReq::SignalLength);
|
||||
|
||||
req->senderData = 19;
|
||||
req->backupDataLen = 0;
|
||||
assert(waitCompleted < 3);
|
||||
req->flags = waitCompleted & 0x3;
|
||||
|
||||
int result;
|
||||
if (waitCompleted == 2) {
|
||||
result = sendRecSignal(nodeId, WAIT_BACKUP_COMPLETED,
|
||||
signal, true, 48*60*60*1000 /* 48 hours */);
|
||||
}
|
||||
else if (waitCompleted == 1) {
|
||||
result = sendRecSignal(nodeId, WAIT_BACKUP_STARTED,
|
||||
signal, true, 5*60*1000 /*5 mins*/);
|
||||
}
|
||||
else {
|
||||
result = sendRecSignal(nodeId, NO_WAIT, signal, true);
|
||||
}
|
||||
if (result == -1) {
|
||||
return SEND_OR_RECEIVE_FAILED;
|
||||
}
|
||||
BackupEvent event;
|
||||
int do_send = 1;
|
||||
while (1) {
|
||||
if (do_send)
|
||||
{
|
||||
SendStatus result = ss.sendSignal(nodeId, &ssig);
|
||||
if (result != SEND_OK) {
|
||||
return SEND_OR_RECEIVE_FAILED;
|
||||
}
|
||||
if (waitCompleted == 0)
|
||||
return 0;
|
||||
do_send = 0;
|
||||
}
|
||||
SimpleSignal *signal = ss.waitFor();
|
||||
|
||||
if (waitCompleted){
|
||||
switch(m_lastBackupEvent.Event){
|
||||
case BackupEvent::BackupCompleted:
|
||||
backupId = m_lastBackupEvent.Completed.BackupId;
|
||||
int gsn = signal->readSignalNumber();
|
||||
switch (gsn) {
|
||||
case GSN_BACKUP_CONF:{
|
||||
const BackupConf * const conf =
|
||||
CAST_CONSTPTR(BackupConf, signal->getDataPtr());
|
||||
event.Event = BackupEvent::BackupStarted;
|
||||
event.Started.BackupId = conf->backupId;
|
||||
event.Nodes = conf->nodes;
|
||||
#ifdef VM_TRACE
|
||||
ndbout_c("Backup(%d) master is %d", conf->backupId,
|
||||
refToNode(signal->header.theSendersBlockRef));
|
||||
#endif
|
||||
backupId = conf->backupId;
|
||||
if (waitCompleted == 1)
|
||||
return 0;
|
||||
// wait for next signal
|
||||
break;
|
||||
case BackupEvent::BackupStarted:
|
||||
backupId = m_lastBackupEvent.Started.BackupId;
|
||||
}
|
||||
case GSN_BACKUP_COMPLETE_REP:{
|
||||
const BackupCompleteRep * const rep =
|
||||
CAST_CONSTPTR(BackupCompleteRep, signal->getDataPtr());
|
||||
#ifdef VM_TRACE
|
||||
ndbout_c("Backup(%d) completed %d", rep->backupId);
|
||||
#endif
|
||||
event.Event = BackupEvent::BackupCompleted;
|
||||
event.Completed.BackupId = rep->backupId;
|
||||
|
||||
event.Completed.NoOfBytes = rep->noOfBytes;
|
||||
event.Completed.NoOfLogBytes = rep->noOfLogBytes;
|
||||
event.Completed.NoOfRecords = rep->noOfRecords;
|
||||
event.Completed.NoOfLogRecords = rep->noOfLogRecords;
|
||||
event.Completed.stopGCP = rep->stopGCP;
|
||||
event.Completed.startGCP = rep->startGCP;
|
||||
event.Nodes = rep->nodes;
|
||||
|
||||
backupId = rep->backupId;
|
||||
return 0;
|
||||
}
|
||||
case GSN_BACKUP_REF:{
|
||||
const BackupRef * const ref =
|
||||
CAST_CONSTPTR(BackupRef, signal->getDataPtr());
|
||||
if(ref->errorCode == BackupRef::IAmNotMaster){
|
||||
nodeId = refToNode(ref->masterRef);
|
||||
#ifdef VM_TRACE
|
||||
ndbout_c("I'm not master resending to %d", nodeId);
|
||||
#endif
|
||||
do_send = 1; // try again
|
||||
continue;
|
||||
}
|
||||
event.Event = BackupEvent::BackupFailedToStart;
|
||||
event.FailedToStart.ErrorCode = ref->errorCode;
|
||||
return ref->errorCode;
|
||||
}
|
||||
case GSN_BACKUP_ABORT_REP:{
|
||||
const BackupAbortRep * const rep =
|
||||
CAST_CONSTPTR(BackupAbortRep, signal->getDataPtr());
|
||||
event.Event = BackupEvent::BackupAborted;
|
||||
event.Aborted.Reason = rep->reason;
|
||||
event.Aborted.BackupId = rep->backupId;
|
||||
event.Aborted.ErrorCode = rep->reason;
|
||||
#ifdef VM_TRACE
|
||||
ndbout_c("Backup %d aborted", rep->backupId);
|
||||
#endif
|
||||
return rep->reason;
|
||||
}
|
||||
case GSN_NF_COMPLETEREP:{
|
||||
const NFCompleteRep * const rep =
|
||||
CAST_CONSTPTR(NFCompleteRep, signal->getDataPtr());
|
||||
#ifdef VM_TRACE
|
||||
ndbout_c("Node %d fail completed", rep->failedNodeId);
|
||||
#endif
|
||||
if (rep->failedNodeId == nodeId ||
|
||||
waitCompleted == 1)
|
||||
return 1326;
|
||||
// wait for next signal
|
||||
// master node will report aborted backup
|
||||
break;
|
||||
case BackupEvent::BackupFailedToStart:
|
||||
return m_lastBackupEvent.FailedToStart.ErrorCode;
|
||||
case BackupEvent::BackupAborted:
|
||||
return m_lastBackupEvent.Aborted.ErrorCode;
|
||||
}
|
||||
case GSN_NODE_FAILREP:{
|
||||
const NodeFailRep * const rep =
|
||||
CAST_CONSTPTR(NodeFailRep, signal->getDataPtr());
|
||||
#ifdef VM_TRACE
|
||||
ndbout_c("Node %d failed", rep->failNo);
|
||||
#endif
|
||||
if (rep->failNo == nodeId ||
|
||||
waitCompleted == 1)
|
||||
return 1326;
|
||||
// wait for next signal
|
||||
// master node will report aborted backup
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return -1;
|
||||
break;
|
||||
report_unknown_signal(signal);
|
||||
return SEND_OR_RECEIVE_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2555,36 +2573,6 @@ MgmtSrvr::abortBackup(Uint32 backupId)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
MgmtSrvr::backupCallback(BackupEvent & event)
|
||||
{
|
||||
DBUG_ENTER("MgmtSrvr::backupCallback");
|
||||
m_lastBackupEvent = event;
|
||||
switch(event.Event){
|
||||
case BackupEvent::BackupFailedToStart:
|
||||
DBUG_PRINT("info",("BackupEvent::BackupFailedToStart"));
|
||||
theWaitState = NO_WAIT;
|
||||
break;
|
||||
case BackupEvent::BackupAborted:
|
||||
DBUG_PRINT("info",("BackupEvent::BackupAborted"));
|
||||
theWaitState = NO_WAIT;
|
||||
break;
|
||||
case BackupEvent::BackupCompleted:
|
||||
DBUG_PRINT("info",("BackupEvent::BackupCompleted"));
|
||||
theWaitState = NO_WAIT;
|
||||
break;
|
||||
case BackupEvent::BackupStarted:
|
||||
if(theWaitState == WAIT_BACKUP_STARTED)
|
||||
{
|
||||
DBUG_PRINT("info",("BackupEvent::BackupStarted NO_WAIT"));
|
||||
theWaitState = NO_WAIT;
|
||||
} else {
|
||||
DBUG_PRINT("info",("BackupEvent::BackupStarted"));
|
||||
}
|
||||
}
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* Global Replication
|
||||
|
|
|
|||
|
|
@ -768,9 +768,6 @@ private:
|
|||
static void *signalRecvThread_C(void *);
|
||||
void signalRecvThreadRun();
|
||||
|
||||
void backupCallback(BackupEvent &);
|
||||
BackupEvent m_lastBackupEvent;
|
||||
|
||||
Config *_props;
|
||||
|
||||
int send(class NdbApiSignal* signal, Uint32 node, Uint32 node_type);
|
||||
|
|
|
|||
|
|
@ -34,7 +34,8 @@ libndbapi_la_SOURCES = \
|
|||
NdbDictionaryImpl.cpp \
|
||||
DictCache.cpp \
|
||||
ndb_cluster_connection.cpp \
|
||||
NdbBlob.cpp
|
||||
NdbBlob.cpp \
|
||||
SignalSender.cpp
|
||||
|
||||
INCLUDES_LOC = -I$(top_srcdir)/storage/ndb/src/mgmapi
|
||||
|
||||
|
|
|
|||
|
|
@ -264,6 +264,7 @@ NdbTransaction::execute(ExecType aTypeOfExec,
|
|||
AbortOption abortOption,
|
||||
int forceSend)
|
||||
{
|
||||
NdbError savedError= theError;
|
||||
DBUG_ENTER("NdbTransaction::execute");
|
||||
DBUG_PRINT("enter", ("aTypeOfExec: %d, abortOption: %d",
|
||||
aTypeOfExec, abortOption));
|
||||
|
|
@ -293,7 +294,11 @@ NdbTransaction::execute(ExecType aTypeOfExec,
|
|||
NdbBlob* tBlob = tPrepOp->theBlobList;
|
||||
while (tBlob != NULL) {
|
||||
if (tBlob->preExecute(tExecType, batch) == -1)
|
||||
{
|
||||
ret = -1;
|
||||
if(savedError.code==0)
|
||||
savedError= theError;
|
||||
}
|
||||
tBlob = tBlob->theNext;
|
||||
}
|
||||
if (batch) {
|
||||
|
|
@ -322,7 +327,11 @@ NdbTransaction::execute(ExecType aTypeOfExec,
|
|||
NdbBlob* tBlob = tOp->theBlobList;
|
||||
while (tBlob != NULL) {
|
||||
if (tBlob->preCommit() == -1)
|
||||
ret = -1;
|
||||
{
|
||||
ret = -1;
|
||||
if(savedError.code==0)
|
||||
savedError= theError;
|
||||
}
|
||||
tBlob = tBlob->theNext;
|
||||
}
|
||||
}
|
||||
|
|
@ -344,7 +353,12 @@ NdbTransaction::execute(ExecType aTypeOfExec,
|
|||
}
|
||||
|
||||
if (executeNoBlobs(tExecType, abortOption, forceSend) == -1)
|
||||
ret = -1;
|
||||
{
|
||||
ret = -1;
|
||||
if(savedError.code==0)
|
||||
savedError= theError;
|
||||
}
|
||||
|
||||
#ifdef ndb_api_crash_on_complex_blob_abort
|
||||
assert(theFirstOpInList == NULL && theLastOpInList == NULL);
|
||||
#else
|
||||
|
|
@ -359,7 +373,11 @@ NdbTransaction::execute(ExecType aTypeOfExec,
|
|||
while (tBlob != NULL) {
|
||||
// may add new operations if batch
|
||||
if (tBlob->postExecute(tExecType) == -1)
|
||||
{
|
||||
ret = -1;
|
||||
if(savedError.code==0)
|
||||
savedError= theError;
|
||||
}
|
||||
tBlob = tBlob->theNext;
|
||||
}
|
||||
}
|
||||
|
|
@ -390,6 +408,10 @@ NdbTransaction::execute(ExecType aTypeOfExec,
|
|||
ndbout << "completed ops: " << n << endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(savedError.code!=0 && theError.code==4350) // Trans already aborted
|
||||
theError= savedError;
|
||||
|
||||
DBUG_RETURN(ret);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -50,14 +50,17 @@ NdbBackup::start(unsigned int & _backup_id){
|
|||
2, // wait until completed
|
||||
&_backup_id,
|
||||
&reply) == -1) {
|
||||
g_err << "Could not start backup " << endl;
|
||||
g_err << "Error: " << reply.message << endl;
|
||||
g_err << "Error: " << ndb_mgm_get_latest_error(handle) << endl;
|
||||
g_err << "Error msg: " << ndb_mgm_get_latest_error_msg(handle) << endl;
|
||||
g_err << "Error desc: " << ndb_mgm_get_latest_error_desc(handle) << endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(reply.return_code != 0){
|
||||
g_err << "PLEASE CHECK CODE NdbBackup.cpp line=" << __LINE__ << endl;
|
||||
g_err << "Error: " << reply.message << endl;
|
||||
g_err << "Error: " << ndb_mgm_get_latest_error(handle) << endl;
|
||||
g_err << "Error msg: " << ndb_mgm_get_latest_error_msg(handle) << endl;
|
||||
g_err << "Error desc: " << ndb_mgm_get_latest_error_desc(handle) << endl;
|
||||
return reply.return_code;
|
||||
}
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -1933,7 +1933,7 @@ int decimal_mul(decimal_t *from1, decimal_t *from2, decimal_t *to)
|
|||
int intg1=ROUND_UP(from1->intg), intg2=ROUND_UP(from2->intg),
|
||||
frac1=ROUND_UP(from1->frac), frac2=ROUND_UP(from2->frac),
|
||||
intg0=ROUND_UP(from1->intg+from2->intg),
|
||||
frac0=frac1+frac2, error, i, j;
|
||||
frac0=frac1+frac2, error, i, j, d_to_move;
|
||||
dec1 *buf1=from1->buf+intg1, *buf2=from2->buf+intg2, *buf0,
|
||||
*start2, *stop2, *stop1, *start0, carry;
|
||||
|
||||
|
|
@ -2007,6 +2007,20 @@ int decimal_mul(decimal_t *from1, decimal_t *from2, decimal_t *to)
|
|||
}
|
||||
}
|
||||
}
|
||||
buf1= to->buf;
|
||||
d_to_move= intg0 + ROUND_UP(to->frac);
|
||||
while (!*buf1 && (to->intg > DIG_PER_DEC1))
|
||||
{
|
||||
buf1++;
|
||||
to->intg-= DIG_PER_DEC1;
|
||||
d_to_move--;
|
||||
}
|
||||
if (to->buf < buf1)
|
||||
{
|
||||
dec1 *cur_d= to->buf;
|
||||
for (; d_to_move; d_to_move--, cur_d++, buf1++)
|
||||
*cur_d= *buf1;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,8 @@
|
|||
# If you want to affect other MySQL variables, you should make your changes
|
||||
# in the /etc/my.cnf, ~/.my.cnf or other MySQL configuration files.
|
||||
|
||||
# If you change base dir, you must also change datadir
|
||||
# If you change base dir, you must also change datadir. These may get
|
||||
# overwritten by settings in the MySQL configuration files.
|
||||
|
||||
basedir=
|
||||
datadir=
|
||||
|
|
@ -61,8 +62,8 @@ then
|
|||
else
|
||||
bindir="$basedir/bin"
|
||||
datadir="$basedir/data"
|
||||
sbindir="$basedir/bin"
|
||||
libexecdir="$basedir/bin"
|
||||
sbindir="$basedir/sbin"
|
||||
libexecdir="$basedir/libexec"
|
||||
fi
|
||||
|
||||
#
|
||||
|
|
@ -99,8 +100,8 @@ parse_server_arguments() {
|
|||
--basedir=*) basedir=`echo "$arg" | sed -e 's/^[^=]*=//'`
|
||||
bindir="$basedir/bin"
|
||||
datadir="$basedir/data"
|
||||
sbindir="$basedir/bin"
|
||||
libexecdir="$basedir/bin"
|
||||
sbindir="$basedir/sbin"
|
||||
libexecdir="$basedir/libexec"
|
||||
;;
|
||||
--datadir=*) datadir=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
|
||||
--user=*) user=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
|
||||
|
|
@ -240,7 +241,7 @@ case "$mode" in
|
|||
if test -x $libexecdir/mysqlmanager
|
||||
then
|
||||
manager=$libexecdir/mysqlmanager
|
||||
elif test -x $bindir/mysqlmanager
|
||||
elif test -x $sbindir/mysqlmanager
|
||||
then
|
||||
manager=$sbindir/mysqlmanager
|
||||
fi
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue