diff --git a/configure.in b/configure.in index 9b5abe39a6f..26fc2d58b55 100644 --- a/configure.in +++ b/configure.in @@ -7,7 +7,7 @@ AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! # remember to also change ndb version below and update version.c in ndb -AM_INIT_AUTOMAKE(mysql, 5.0.40) +AM_INIT_AUTOMAKE(mysql, 5.0.42) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 @@ -23,7 +23,7 @@ NDB_SHARED_LIB_VERSION=$NDB_SHARED_LIB_MAJOR_VERSION:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=40 +NDB_VERSION_BUILD=42 NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ? diff --git a/mysql-test/r/bdb_notembedded.result b/mysql-test/r/bdb_notembedded.result new file mode 100644 index 00000000000..14cb5fad915 --- /dev/null +++ b/mysql-test/r/bdb_notembedded.result @@ -0,0 +1,35 @@ +set autocommit=1; +reset master; +create table bug16206 (a int); +insert into bug16206 values(1); +start transaction; +insert into bug16206 values(2); +commit; +show binlog events; +Log_name Pos Event_type Server_id End_log_pos Info +f n Format_desc 1 n Server ver: VERSION, Binlog ver: 4 +f n Query 1 n use `test`; create table bug16206 (a int) +f n Query 1 n use `test`; insert into bug16206 values(1) +f n Query 1 n use `test`; insert into bug16206 values(2) +drop table bug16206; +reset master; +create table bug16206 (a int) engine= bdb; +insert into bug16206 values(0); +insert into bug16206 values(1); +start transaction; +insert into bug16206 values(2); +commit; +insert into bug16206 values(3); +show binlog events; +Log_name Pos Event_type Server_id End_log_pos Info +f n Format_desc 1 n Server ver: VERSION, Binlog ver: 4 +f n Query 1 n use `test`; create table bug16206 (a int) engine= bdb +f n Query 1 n use `test`; insert into bug16206 values(0) +f n Query 1 n use `test`; insert into bug16206 values(1) +f n Query 1 n use `test`; BEGIN +f n Query 1 n use `test`; insert into bug16206 values(2) +f n Query 1 n use `test`; COMMIT +f n Query 1 n use `test`; insert into bug16206 values(3) +drop table bug16206; +set autocommit=0; +End of 5.0 tests diff --git a/mysql-test/r/distinct.result b/mysql-test/r/distinct.result index 3508a83a810..190e8595126 100644 --- a/mysql-test/r/distinct.result +++ b/mysql-test/r/distinct.result @@ -668,3 +668,17 @@ NULL 3 4 DROP TABLE t1; +CREATE TABLE t1 (a INT, b INT); +INSERT INTO t1 VALUES(1,1),(1,2),(1,3); +SELECT DISTINCT a, b FROM t1; +a b +1 1 +1 2 +1 3 +SELECT DISTINCT a, a, b FROM t1; +a a b +1 1 1 +1 1 2 +1 1 3 +DROP TABLE t1; +End of 5.0 tests diff --git a/mysql-test/r/ndb_restore.result b/mysql-test/r/ndb_restore.result index e5bf4315e5c..bc31798cee7 100644 --- a/mysql-test/r/ndb_restore.result +++ b/mysql-test/r/ndb_restore.result @@ -1,14 +1,14 @@ use test; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9,t10; drop table if exists t1_c,t2_c,t3_c,t4_c,t5_c,t6_c,t7_c,t8_c,t9_c,t10_c; -CREATE TABLE `t1` ( -`capgoaledatta` smallint(5) unsigned NOT NULL auto_increment, +CREATE TABLE `t1_c` ( +`capgoaledatta` mediumint(5) unsigned NOT NULL auto_increment, `goaledatta` char(2) NOT NULL default '', `maturegarbagefa` varchar(32) NOT NULL default '', PRIMARY KEY (`capgoaledatta`,`goaledatta`,`maturegarbagefa`) -) ENGINE=myisam DEFAULT CHARSET=latin1; -INSERT INTO `t1` VALUES (2,'3','q3plus.qt'),(4,'4','q3plus.qt'),(1,'3','q3.net'),(3,'4','q3.net'),(3,'20','threetrees.qt'); -CREATE TABLE `t2` ( +) ENGINE=ndbcluster DEFAULT CHARSET=latin1; +INSERT INTO `t1_c` VALUES (2,'3','q3plus.qt'),(400,'4','q3plus.qt'),(1,'3','q3.net'),(3,'4','q3.net'),(3000,'20','threetrees.qt'); +CREATE TABLE `t2_c` ( `capgotod` smallint(5) unsigned NOT NULL auto_increment, `gotod` smallint(5) unsigned NOT NULL default '0', `goaledatta` char(2) default NULL, @@ -16,16 +16,16 @@ CREATE TABLE `t2` ( `descrpooppo` varchar(64) default NULL, `svcutonsa` varchar(64) NOT NULL default '', PRIMARY KEY (`capgotod`), -KEY `i_quadaddsvr` (`gotod`) -) ENGINE=myisam DEFAULT CHARSET=latin1; -INSERT INTO `t2` VALUES (5,4,'','q3.net','addavp:MK_CASELECTOR=1','postorod rattoaa'),(2,1,'4','','addavp:MK_BRANDTAD=345','REDS Brandtad'),(3,2,'4','q3.net','execorder','fixedRatediPO REDS'),(1,1,'3','','addavp:MK_BRANDTAD=123','TEST Brandtad'),(6,5,'','told.q3.net','addavp:MK_BRANDTAD=123','Brandtad Toldzone'),(4,3,'3','q3.net','addavp:MK_POOLHINT=2','ratedi PO TEST'); -CREATE TABLE `t3` ( +KEY `i quadaddsvr` (`gotod`) +) ENGINE=ndbcluster DEFAULT CHARSET=latin1; +INSERT INTO `t2_c` VALUES (500,4,'','q3.net','addavp:MK_CASELECTOR=1','postorod rattoaa'),(2,1,'4','','addavp:MK_BRANDTAD=345','REDS Brandtad'),(3,2,'4','q3.net','execorder','fixedRatediPO REDS'),(1,1,'3','','addavp:MK_BRANDTAD=123','TEST Brandtad'),(6,5,'','told.q3.net','addavp:MK_BRANDTAD=123','Brandtad Toldzone'),(4,3,'3','q3.net','addavp:MK_POOLHINT=2','ratedi PO TEST'); +CREATE TABLE `t3_c` ( `CapGoaledatta` smallint(5) unsigned NOT NULL default '0', `capgotod` smallint(5) unsigned NOT NULL default '0', PRIMARY KEY (`capgotod`,`CapGoaledatta`) -) ENGINE=myisam DEFAULT CHARSET=latin1; -INSERT INTO `t3` VALUES (5,3),(2,4),(5,4),(1,3); -CREATE TABLE `t4` ( +) ENGINE=ndbcluster DEFAULT CHARSET=latin1; +INSERT INTO `t3_c` VALUES (5,3),(2,4),(5,4),(1,3); +CREATE TABLE `t4_c` ( `capfa` bigint(20) unsigned NOT NULL auto_increment, `realm` varchar(32) NOT NULL default '', `authpwchap` varchar(32) default NULL, @@ -35,34 +35,34 @@ CREATE TABLE `t4` ( PRIMARY KEY (`fa`,`realm`), KEY `capfa` (`capfa`), KEY `i_quadentity` (`fa`,`realm`) -) ENGINE=myisam DEFAULT CHARSET=latin1; -INSERT INTO `t4` VALUES (18,'john.smith','q3.net','dessjohn.smith',0,NULL),(21,'quad_katt_with_brandtad','q3.net','acne',0,NULL),(22,'quad_katt_carattoaa','q3.net','acne',0,NULL),(26,'436462612809','sqasdt.q3.net','N/A',0,'6'),(19,'john','smith.qt','dessjohn',0,NULL),(33,'436643196120','sqasdt.q3.net','N/A',1,'6'),(28,'436642900019','sqasdt.q3.net','N/A',0,'6'),(30,'436462900209','sqasdt.q3.net','N/A',0,'6'),(16,'436640006666','sqasdt.q3.net','',0,NULL),(19,'dette','el-redun.com','dessdette',0,NULL),(12,'quad_kattPP','q3.net','acne',2,NULL),(14,'436640008888','sqasdt.q3.net','',0,NULL),(29,'463624900028','sqasdt.q3.net','N/A',0,'6'),(15,'436640099099','sqasdt.q3.net','',0,NULL),(13,'pap','q3plus.qt','acne',1,NULL),(19,'436642612091','sqasdt.q3.net','N/A',0,'6'),(12,'quad_katt','q3.net','acne',0,NULL),(11,'quad_kattVK','q3.net','acne',1,NULL),(32,'463641969502','sqasdt.q3.net','N/A',1,'6'),(20,'joe','q3.net','joedesswd',0,NULL),(29,'436642900034','sqasdt.q3.net','N/A',0,'6'),(25,'contind','armerde.qt','acne',1,NULL); -CREATE TABLE `t5` ( +) ENGINE=ndbcluster DEFAULT CHARSET=latin1; +INSERT INTO `t4_c` VALUES (18,'john.smith','q3.net','dessjohn.smith',0,NULL),(21,'quad_katt_with_brandtad','q3.net','acne',0,NULL),(2200,'quad_katt_carattoaa','q3.net','acne',0,NULL),(26,'436462612809','sqasdt.q3.net','N/A',0,'6'),(19,'john','smith.qt','dessjohn',0,NULL),(33,'436643196120','sqasdt.q3.net','N/A',1,'6'),(28,'436642900019','sqasdt.q3.net','N/A',0,'6'),(30,'436462900209','sqasdt.q3.net','N/A',0,'6'),(16,'436640006666','sqasdt.q3.net','',0,NULL),(19,'dette','el-redun.com','dessdette',0,NULL),(12,'quad_kattPP','q3.net','acne',2,NULL),(14,'436640008888','sqasdt.q3.net','',0,NULL),(29,'463624900028','sqasdt.q3.net','N/A',0,'6'),(15,'436640099099','sqasdt.q3.net','',0,NULL),(13,'pap','q3plus.qt','acne',1,NULL),(19,'436642612091','sqasdt.q3.net','N/A',0,'6'),(12,'quad_katt','q3.net','acne',0,NULL),(11,'quad_kattVK','q3.net','acne',1,NULL),(32000,'463641969502','sqasdt.q3.net','N/A',1,'6'),(20,'joe','q3.net','joedesswd',0,NULL),(290000000,'436642900034','sqasdt.q3.net','N/A',0,'6'),(25,'contind','armerde.qt','acne',1,NULL); +CREATE TABLE `t5_c` ( `capfa` bigint(20) unsigned NOT NULL default '0', `gotod` smallint(5) unsigned NOT NULL default '0', `orderutonsa` varchar(64) NOT NULL default '', PRIMARY KEY (`capfa`,`gotod`,`orderutonsa`) -) ENGINE=myisam DEFAULT CHARSET=latin1; -INSERT INTO `t5` VALUES (21,2,''),(21,1,''),(22,4,''); -CREATE TABLE `t6` ( +) ENGINE=ndbcluster DEFAULT CHARSET=latin1; +INSERT INTO `t5_c` VALUES (21,2,''),(21,1,''),(22,4,''); +CREATE TABLE `t6_c` ( `capfa_parent` bigint(20) unsigned NOT NULL default '0', `capfa_child` bigint(20) unsigned NOT NULL default '0', `relatta` smallint(5) unsigned NOT NULL default '0', PRIMARY KEY (`capfa_child`,`capfa_parent`,`relatta`) -) ENGINE=myisam DEFAULT CHARSET=latin1; -INSERT INTO `t6` VALUES (15,16,0),(19,20,0),(18326932092909551615,30,0),(26,29,0),(18326932092909551615,29,0),(19,18,0),(26,28,0),(12,14,0); -CREATE TABLE `t7` ( +) ENGINE=ndbcluster DEFAULT CHARSET=latin1; +INSERT INTO `t6_c` VALUES (15,16,0),(19,20,0),(18326932092909551615,30,0),(26,29,0),(18326932092909551615,29,0),(19,18,0),(26,28,0),(12,14,0); +CREATE TABLE `t7_c` ( `dardpo` char(15) NOT NULL default '', -`dardtestard` tinyint(3) unsigned NOT NULL default '0', +`dardtestard` tinyint(3) unsigned NOT NULL auto_increment, `FastFA` char(5) NOT NULL default '', `FastCode` char(6) NOT NULL default '', `Fastca` char(1) NOT NULL default '', `Fastmag` char(1) NOT NULL default '', `Beareratta` char(2) NOT NULL default '', PRIMARY KEY (`dardpo`,`dardtestard`) -) ENGINE=myisam DEFAULT CHARSET=latin1; -INSERT INTO `t7` VALUES ('2.6.2.4',24,'CECHP','54545','0','0','5'),('2.2.5.4',26,'CANFA','33223','1','1','4'),('4.3.2.4',28,'ITALD','54222','1','0','5'),('129..0.0.eins',28,'G','99999','1','1','5'),('1.1.1.1',24,'AUTPT','32323','0','1','3'); -CREATE TABLE `t8` ( +) ENGINE=ndbcluster DEFAULT CHARSET=latin1; +INSERT INTO `t7_c` VALUES ('2.6.2.4',24,'CECHP','54545','0','0','5'),('2.2.5.4',26,'CANFA','33223','1','1','4'),('4.3.2.4',28,'ITALD','54222','1','0','5'),('129..0.0.eins',28,'G','99999','1','1','5'),('1.1.1.1',24,'AUTPT','32323','0','1','3'); +CREATE TABLE `t8_c` ( `kattjame` varchar(32) NOT NULL default '', `realm` varchar(32) NOT NULL default '', `realm_entered` varchar(32) NOT NULL default '', @@ -88,9 +88,9 @@ CREATE TABLE `t8` ( `acctinputoctets` bigint(20) unsigned default NULL, PRIMARY KEY (`kattjame`,`hunderaaarbagefa`,`hassetistart`,`hassetino`), KEY `squardporoot` (`squardporoot`) -) ENGINE=myisam DEFAULT CHARSET=latin1; -INSERT INTO `t8` VALUES ('4tt45345235','pap','q3plus.qt','q3plus.qt','q3.net','436643196120','436643196929','8956234534568968','5524595699','uxasmt21.net.acne.qt/481889229462692422','','1.1.1.1','2.2.4.6','4','86989','34','x','x','2012-03-12 12:55:34','2012-12-05 11:20:04',3223433,3369,9565),('4545435545','john','q3.net','q3.net','acne.li','436643196120','436643196929','45345234568968','995696699','uxasmt21.net.acne.qt/481889229462692423','','1.1.1.1','2.2.9.8','2','86989','34','x','x','2012-03-12 11:35:03','2012-12-05 08:50:04',8821923,169,3565),('versteckter_q3net_katt','joe','q3.net','elredun.com','q3.net','436643196120','436643196939','91341234568968','695595699','uxasmt21.net.acne.qt/481889229462692421','','1.1.1.1','2.5.2.5','3','86989','34','x','x','2012-03-12 18:35:04','2012-12-05 12:35:04',1923123,9569,6565); -CREATE TABLE `t9` ( +) ENGINE=ndbcluster DEFAULT CHARSET=latin1; +INSERT INTO `t8_c` VALUES ('4tt45345235','pap','q3plus.qt','q3plus.qt','q3.net','436643196120','436643196929','8956234534568968','5524595699','uxasmt21.net.acne.qt/481889229462692422','','1.1.1.1','2.2.4.6','4','86989','34','x','x','2012-03-12 12:55:34','2012-12-05 11:20:04',3223433,3369,9565),('4545435545','john','q3.net','q3.net','acne.li','436643196120','436643196929','45345234568968','995696699','uxasmt21.net.acne.qt/481889229462692423','','1.1.1.1','2.2.9.8','2','86989','34','x','x','2012-03-12 11:35:03','2012-12-05 08:50:04',8821923,169,3565),('versteckter_q3net_katt','joe','q3.net','elredun.com','q3.net','436643196120','436643196939','91341234568968','695595699','uxasmt21.net.acne.qt/481889229462692421','','1.1.1.1','2.5.2.5','3','86989','34','x','x','2012-03-12 18:35:04','2012-12-05 12:35:04',1923123,9569,6565); +CREATE TABLE `t9_c` ( `kattjame` varchar(32) NOT NULL default '', `kattjame_entered` varchar(32) NOT NULL default '', `realm` varchar(32) NOT NULL default '', @@ -114,20 +114,21 @@ CREATE TABLE `t9` ( `actinputocctets` bigint(20) unsigned default NULL, `terminateraste` tinyint(3) unsigned default NULL, PRIMARY KEY (`kattjame`,`hunderaaarbagefa`,`hassetistart`,`hassetino`) -) ENGINE=myisam DEFAULT CHARSET=latin1; -INSERT INTO `t9` VALUES ('3g4jh8gar2t','joe','q3.net','elredun.com','q3.net','436643316120','436643316939','91341234568968','695595699','1.1.1.1','2.2.6.2','3','86989','34','x','x','2012-03-12 18:35:04','2012-12-05 12:35:04',3123123,9569,6565,1),('4tt45345235','pap','q3plus.qt','q3plus.qt','q3.net','436643316120','436643316939','8956234534568968','5254595969','1.1.1.1','8.6.2.2','4','86989','34','x','x','2012-03-12 12:55:34','2012-12-05 11:20:04',3223433,3369,9565,2),('4545435545','john','q3.net','q3.net','acne.li','436643316120','436643316939','45345234568968','995696699','1.1.1.1','2.9.9.2','2','86998','34','x','x','2012-03-12 11:35:03','2012-12-05 08:50:04',8823123,169,3565,3); -create table t10 (a int auto_increment key); -insert into t10 values (1),(2),(3); -create table t1_c engine=ndbcluster as select * from t1; -create table t2_c engine=ndbcluster as select * from t2; -create table t3_c engine=ndbcluster as select * from t3; -create table t4_c engine=ndbcluster as select * from t4; -create table t5_c engine=ndbcluster as select * from t5; -create table t6_c engine=ndbcluster as select * from t6; -create table t7_c engine=ndbcluster as select * from t7; -create table t8_c engine=ndbcluster as select * from t8; -create table t9_c engine=ndbcluster as select * from t9; -create table t10_c engine=ndbcluster as select * from t10; +) ENGINE=ndbcluster DEFAULT CHARSET=latin1; +INSERT INTO `t9_c` VALUES ('3g4jh8gar2t','joe','q3.net','elredun.com','q3.net','436643316120','436643316939','91341234568968','695595699','1.1.1.1','2.2.6.2','3','86989','34','x','x','2012-03-12 18:35:04','2012-12-05 12:35:04',3123123,9569,6565,1),('4tt45345235','pap','q3plus.qt','q3plus.qt','q3.net','436643316120','436643316939','8956234534568968','5254595969','1.1.1.1','8.6.2.2','4','86989','34','x','x','2012-03-12 12:55:34','2012-12-05 11:20:04',3223433,3369,9565,2),('4545435545','john','q3.net','q3.net','acne.li','436643316120','436643316939','45345234568968','995696699','1.1.1.1','2.9.9.2','2','86998','34','x','x','2012-03-12 11:35:03','2012-12-05 08:50:04',8823123,169,3565,3); +create table t10_c (a int auto_increment key) ENGINE=ndbcluster; +insert into t10_c values (1),(2),(3); +insert into t10_c values (10000),(2000),(3000); +create table t1 engine=myisam as select * from t1_c; +create table t2 engine=myisam as select * from t2_c; +create table t3 engine=myisam as select * from t3_c; +create table t4 engine=myisam as select * from t4_c; +create table t5 engine=myisam as select * from t5_c; +create table t6 engine=myisam as select * from t6_c; +create table t7 engine=myisam as select * from t7_c; +create table t8 engine=myisam as select * from t8_c; +create table t9 engine=myisam as select * from t9_c; +create table t10 engine=myisam as select * from t10_c; drop table t1_c,t2_c,t3_c,t4_c,t5_c,t6_c,t7_c,t8_c,t9_c, t10_c; show tables; Tables_in_test @@ -255,6 +256,24 @@ a 1 2 3 +2000 +3000 +10000 +show table status like 't1_c'; +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 +X X X X X X X X X X 3001 X X X X X X X +show table status like 't2_c'; +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 +X X X X X X X X X X 501 X X X X X X X +show table status like 't4_c'; +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 +X X X X X X X X X X 290000001 X X X X X X X +show table status like 't7_c'; +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 +X X X X X X X X X X 29 X X X X X X X +show table status like 't10_c'; +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 +X X X X X X X X X X 10001 X X X X X X X drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9, t10; drop table if exists t1_c,t2_c,t3_c,t4_c,t5_c,t6_c,t7_c,t8_c,t9_c, t10_c; 520093696,1 diff --git a/mysql-test/r/row.result b/mysql-test/r/row.result index faf9b11d7c9..bb9e2109f0f 100644 --- a/mysql-test/r/row.result +++ b/mysql-test/r/row.result @@ -175,6 +175,24 @@ ROW(2,10) <=> ROW(3,4) SELECT ROW(NULL,10) <=> ROW(3,NULL); ROW(NULL,10) <=> ROW(3,NULL) 0 +SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),ROW(1,1)); +ERROR 21000: Operand should contain 2 column(s) +SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),ROW(1,1),ROW(1,ROW(2,3))); +ERROR 21000: Operand should contain 2 column(s) +SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),ROW(1,ROW(2,2,2))); +ERROR 21000: Operand should contain 2 column(s) +SELECT ROW(1,ROW(2,3,4)) IN (ROW(1,ROW(2,3,4)),ROW(1,ROW(2,2))); +ERROR 21000: Operand should contain 3 column(s) +SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),(SELECT 1,1)); +ERROR 21000: Operand should contain 2 column(s) +SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),(SELECT 1,1),ROW(1,ROW(2,4))); +ERROR 21000: Operand should contain 2 column(s) +SELECT ROW(1,ROW(2,3)) IN ((SELECT 1,1),ROW(1,ROW(2,3))); +ERROR 21000: Operand should contain 2 column(s) +SELECT ROW(2,1) IN (ROW(21,2),ROW(ROW(1,1,3),0)); +ERROR 21000: Operand should contain 1 column(s) +SELECT ROW(2,1) IN (ROW(ROW(1,1,3),0),ROW(21,2)); +ERROR 21000: Operand should contain 1 column(s) SELECT ROW(1,1,1) = ROW(1,1,1) as `1`, ROW(1,1,1) = ROW(1,2,1) as `0`, ROW(1,NULL,1) = ROW(2,2,1) as `0`, ROW(1,NULL,1) = ROW(1,2,2) as `0`, ROW(1,NULL,1) = ROW(1,2,1) as `null` ; 1 0 0 0 null 1 0 0 0 NULL diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index b501d547e0a..bfe0b9d19df 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -3986,4 +3986,13 @@ t2.access_id IN (1,4) AND t.access_id IS NULL AND t2.faq_id in (265); faq_id 265 DROP TABLE t1,t2; +CREATE TABLE t1 (a INT, b INT, KEY inx (b,a)); +INSERT INTO t1 VALUES (1,1), (1,2), (1,3), (1,4), (1,5), (1, 6), (1,7); +EXPLAIN SELECT COUNT(*) FROM t1 f1 INNER JOIN t1 f2 +ON ( f1.b=f2.b AND f1.a 0 GROUP BY a; diff --git a/mysql-test/r/subselect3.result b/mysql-test/r/subselect3.result index 96a3ee00a59..33e7fc54ed2 100644 --- a/mysql-test/r/subselect3.result +++ b/mysql-test/r/subselect3.result @@ -432,7 +432,7 @@ alter table t1 add index idx(oref,ie); explain select oref, a, a in (select ie from t1 where oref=t2.oref) Z from t2; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t2 ALL NULL NULL NULL NULL 7 -2 DEPENDENT SUBQUERY t1 ref_or_null idx idx 10 t2.oref,func 4 Using where; Using index; Full scan on NULL key +2 DEPENDENT SUBQUERY t1 ref_or_null idx idx 10 test.t2.oref,func 4 Using where; Using index; Full scan on NULL key select oref, a, a in (select ie from t1 where oref=t2.oref) Z from t2; oref a Z ee NULL NULL @@ -457,7 +457,7 @@ group by grp having min(ie) > 1) Z from t2; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t2 ALL NULL NULL NULL NULL 7 -2 DEPENDENT SUBQUERY t1 ref idx idx 5 t2.oref 2 Using where; Using temporary; Using filesort +2 DEPENDENT SUBQUERY t1 ref idx idx 5 test.t2.oref 2 Using where; Using temporary; Using filesort select oref, a, a in (select min(ie) from t1 where oref=t2.oref group by grp having min(ie) > 1) Z diff --git a/mysql-test/r/truncate.result b/mysql-test/r/truncate.result index 74a6cb72cc6..6c21db0e2b8 100644 --- a/mysql-test/r/truncate.result +++ b/mysql-test/r/truncate.result @@ -53,3 +53,30 @@ a 3 4 drop table t1; +create table t1 (s1 int); +insert into t1 (s1) values (1), (2), (3), (4), (5); +create view v1 as select * from t1; +truncate table v1; +select count(*) from t1; +count(*) +0 +insert into t1 (s1) values (1), (2), (3), (4), (5); +create view v2 as select * from t1 where s1 > 3; +truncate table v2; +select * from t1; +s1 +1 +2 +3 +select * from v2; +s1 +delete from t1; +create table t2 (s1 int, s2 int); +create view v3 as select a.s1, b.s2 from t1 a join t2 b on a.s1 = b.s1 where a.s1 > 3; +truncate table v3; +ERROR HY000: Can not delete from join view 'test.v3' +create view v4 as select * from t1 limit 1,1; +truncate table v4; +ERROR HY000: The target table v4 of the TRUNCATE is not updatable +drop view v1, v2, v3, v4; +drop table t1, t2; diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index dc87f97b322..71d743f37b9 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -2395,6 +2395,16 @@ Table Op Msg_type Msg_text test.v1 optimize error 'test.v1' is not BASE TABLE Warnings: Error 1347 'test.v1' is not BASE TABLE +ANALYZE TABLE v1; +Table Op Msg_type Msg_text +test.v1 analyze error 'test.v1' is not BASE TABLE +Warnings: +Error 1347 'test.v1' is not BASE TABLE +REPAIR TABLE v1; +Table Op Msg_type Msg_text +test.v1 repair error 'test.v1' is not BASE TABLE +Warnings: +Error 1347 'test.v1' is not BASE TABLE DROP VIEW v1; create definer = current_user() sql security invoker view v1 as select 1; show create view v1; diff --git a/mysql-test/t/bdb_notembedded.test b/mysql-test/t/bdb_notembedded.test new file mode 100644 index 00000000000..24e64ebbfb2 --- /dev/null +++ b/mysql-test/t/bdb_notembedded.test @@ -0,0 +1,38 @@ +-- source include/not_embedded.inc +-- source include/have_bdb.inc + +# +# Bug #16206: Superfluous COMMIT event in binlog when updating BDB in autocommit mode +# +set autocommit=1; + +let $VERSION=`select version()`; + +reset master; +create table bug16206 (a int); +insert into bug16206 values(1); +start transaction; +insert into bug16206 values(2); +commit; +--replace_result $VERSION VERSION +--replace_column 1 f 2 n 5 n +show binlog events; +drop table bug16206; + +reset master; +create table bug16206 (a int) engine= bdb; +insert into bug16206 values(0); +insert into bug16206 values(1); +start transaction; +insert into bug16206 values(2); +commit; +insert into bug16206 values(3); +--replace_result $VERSION VERSION +--replace_column 1 f 2 n 5 n +show binlog events; +drop table bug16206; + +set autocommit=0; + + +--echo End of 5.0 tests diff --git a/mysql-test/t/distinct.test b/mysql-test/t/distinct.test index 476e4ce7735..7310f98cd16 100644 --- a/mysql-test/t/distinct.test +++ b/mysql-test/t/distinct.test @@ -540,3 +540,16 @@ EXPLAIN SELECT a FROM t1 GROUP BY a; SELECT a FROM t1 GROUP BY a; DROP TABLE t1; + +# +#Bug #27659: SELECT DISTINCT returns incorrect result set when field is +#repeated +# +# +CREATE TABLE t1 (a INT, b INT); +INSERT INTO t1 VALUES(1,1),(1,2),(1,3); +SELECT DISTINCT a, b FROM t1; +SELECT DISTINCT a, a, b FROM t1; +DROP TABLE t1; + +--echo End of 5.0 tests diff --git a/mysql-test/t/ndb_restore.test b/mysql-test/t/ndb_restore.test index 39c7ab67efb..5b839a0d3aa 100644 --- a/mysql-test/t/ndb_restore.test +++ b/mysql-test/t/ndb_restore.test @@ -8,15 +8,22 @@ drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9,t10; drop table if exists t1_c,t2_c,t3_c,t4_c,t5_c,t6_c,t7_c,t8_c,t9_c,t10_c; --enable_warnings -CREATE TABLE `t1` ( - `capgoaledatta` smallint(5) unsigned NOT NULL auto_increment, +# Bug #27775 - mediumint auto inc not restored correctly +# - check mediumint +CREATE TABLE `t1_c` ( + `capgoaledatta` mediumint(5) unsigned NOT NULL auto_increment, `goaledatta` char(2) NOT NULL default '', `maturegarbagefa` varchar(32) NOT NULL default '', PRIMARY KEY (`capgoaledatta`,`goaledatta`,`maturegarbagefa`) -) ENGINE=myisam DEFAULT CHARSET=latin1; -INSERT INTO `t1` VALUES (2,'3','q3plus.qt'),(4,'4','q3plus.qt'),(1,'3','q3.net'),(3,'4','q3.net'),(3,'20','threetrees.qt'); - -CREATE TABLE `t2` ( +) ENGINE=ndbcluster DEFAULT CHARSET=latin1; +INSERT INTO `t1_c` VALUES (2,'3','q3plus.qt'),(400,'4','q3plus.qt'),(1,'3','q3.net'),(3,'4','q3.net'),(3000,'20','threetrees.qt'); +# +# Bug #27758 Restoring NDB backups makes table usable in SQL nodes +# - space in key made table unusable after restore +# +# Bug #27775 - mediumint auto inc not restored correctly +# - check smallint +CREATE TABLE `t2_c` ( `capgotod` smallint(5) unsigned NOT NULL auto_increment, `gotod` smallint(5) unsigned NOT NULL default '0', `goaledatta` char(2) default NULL, @@ -24,18 +31,20 @@ CREATE TABLE `t2` ( `descrpooppo` varchar(64) default NULL, `svcutonsa` varchar(64) NOT NULL default '', PRIMARY KEY (`capgotod`), - KEY `i_quadaddsvr` (`gotod`) -) ENGINE=myisam DEFAULT CHARSET=latin1; -INSERT INTO `t2` VALUES (5,4,'','q3.net','addavp:MK_CASELECTOR=1','postorod rattoaa'),(2,1,'4','','addavp:MK_BRANDTAD=345','REDS Brandtad'),(3,2,'4','q3.net','execorder','fixedRatediPO REDS'),(1,1,'3','','addavp:MK_BRANDTAD=123','TEST Brandtad'),(6,5,'','told.q3.net','addavp:MK_BRANDTAD=123','Brandtad Toldzone'),(4,3,'3','q3.net','addavp:MK_POOLHINT=2','ratedi PO TEST'); + KEY `i quadaddsvr` (`gotod`) +) ENGINE=ndbcluster DEFAULT CHARSET=latin1; +INSERT INTO `t2_c` VALUES (500,4,'','q3.net','addavp:MK_CASELECTOR=1','postorod rattoaa'),(2,1,'4','','addavp:MK_BRANDTAD=345','REDS Brandtad'),(3,2,'4','q3.net','execorder','fixedRatediPO REDS'),(1,1,'3','','addavp:MK_BRANDTAD=123','TEST Brandtad'),(6,5,'','told.q3.net','addavp:MK_BRANDTAD=123','Brandtad Toldzone'),(4,3,'3','q3.net','addavp:MK_POOLHINT=2','ratedi PO TEST'); -CREATE TABLE `t3` ( +CREATE TABLE `t3_c` ( `CapGoaledatta` smallint(5) unsigned NOT NULL default '0', `capgotod` smallint(5) unsigned NOT NULL default '0', PRIMARY KEY (`capgotod`,`CapGoaledatta`) -) ENGINE=myisam DEFAULT CHARSET=latin1; -INSERT INTO `t3` VALUES (5,3),(2,4),(5,4),(1,3); +) ENGINE=ndbcluster DEFAULT CHARSET=latin1; +INSERT INTO `t3_c` VALUES (5,3),(2,4),(5,4),(1,3); -CREATE TABLE `t4` ( +# Bug #27775 - mediumint auto inc not restored correctly +# - check bigint +CREATE TABLE `t4_c` ( `capfa` bigint(20) unsigned NOT NULL auto_increment, `realm` varchar(32) NOT NULL default '', `authpwchap` varchar(32) default NULL, @@ -45,38 +54,40 @@ CREATE TABLE `t4` ( PRIMARY KEY (`fa`,`realm`), KEY `capfa` (`capfa`), KEY `i_quadentity` (`fa`,`realm`) -) ENGINE=myisam DEFAULT CHARSET=latin1; -INSERT INTO `t4` VALUES (18,'john.smith','q3.net','dessjohn.smith',0,NULL),(21,'quad_katt_with_brandtad','q3.net','acne',0,NULL),(22,'quad_katt_carattoaa','q3.net','acne',0,NULL),(26,'436462612809','sqasdt.q3.net','N/A',0,'6'),(19,'john','smith.qt','dessjohn',0,NULL),(33,'436643196120','sqasdt.q3.net','N/A',1,'6'),(28,'436642900019','sqasdt.q3.net','N/A',0,'6'),(30,'436462900209','sqasdt.q3.net','N/A',0,'6'),(16,'436640006666','sqasdt.q3.net','',0,NULL),(19,'dette','el-redun.com','dessdette',0,NULL),(12,'quad_kattPP','q3.net','acne',2,NULL),(14,'436640008888','sqasdt.q3.net','',0,NULL),(29,'463624900028','sqasdt.q3.net','N/A',0,'6'),(15,'436640099099','sqasdt.q3.net','',0,NULL),(13,'pap','q3plus.qt','acne',1,NULL),(19,'436642612091','sqasdt.q3.net','N/A',0,'6'),(12,'quad_katt','q3.net','acne',0,NULL),(11,'quad_kattVK','q3.net','acne',1,NULL),(32,'463641969502','sqasdt.q3.net','N/A',1,'6'),(20,'joe','q3.net','joedesswd',0,NULL),(29,'436642900034','sqasdt.q3.net','N/A',0,'6'),(25,'contind','armerde.qt','acne',1,NULL); +) ENGINE=ndbcluster DEFAULT CHARSET=latin1; +INSERT INTO `t4_c` VALUES (18,'john.smith','q3.net','dessjohn.smith',0,NULL),(21,'quad_katt_with_brandtad','q3.net','acne',0,NULL),(2200,'quad_katt_carattoaa','q3.net','acne',0,NULL),(26,'436462612809','sqasdt.q3.net','N/A',0,'6'),(19,'john','smith.qt','dessjohn',0,NULL),(33,'436643196120','sqasdt.q3.net','N/A',1,'6'),(28,'436642900019','sqasdt.q3.net','N/A',0,'6'),(30,'436462900209','sqasdt.q3.net','N/A',0,'6'),(16,'436640006666','sqasdt.q3.net','',0,NULL),(19,'dette','el-redun.com','dessdette',0,NULL),(12,'quad_kattPP','q3.net','acne',2,NULL),(14,'436640008888','sqasdt.q3.net','',0,NULL),(29,'463624900028','sqasdt.q3.net','N/A',0,'6'),(15,'436640099099','sqasdt.q3.net','',0,NULL),(13,'pap','q3plus.qt','acne',1,NULL),(19,'436642612091','sqasdt.q3.net','N/A',0,'6'),(12,'quad_katt','q3.net','acne',0,NULL),(11,'quad_kattVK','q3.net','acne',1,NULL),(32000,'463641969502','sqasdt.q3.net','N/A',1,'6'),(20,'joe','q3.net','joedesswd',0,NULL),(290000000,'436642900034','sqasdt.q3.net','N/A',0,'6'),(25,'contind','armerde.qt','acne',1,NULL); -CREATE TABLE `t5` ( +CREATE TABLE `t5_c` ( `capfa` bigint(20) unsigned NOT NULL default '0', `gotod` smallint(5) unsigned NOT NULL default '0', `orderutonsa` varchar(64) NOT NULL default '', PRIMARY KEY (`capfa`,`gotod`,`orderutonsa`) -) ENGINE=myisam DEFAULT CHARSET=latin1; -INSERT INTO `t5` VALUES (21,2,''),(21,1,''),(22,4,''); +) ENGINE=ndbcluster DEFAULT CHARSET=latin1; +INSERT INTO `t5_c` VALUES (21,2,''),(21,1,''),(22,4,''); -CREATE TABLE `t6` ( +CREATE TABLE `t6_c` ( `capfa_parent` bigint(20) unsigned NOT NULL default '0', `capfa_child` bigint(20) unsigned NOT NULL default '0', `relatta` smallint(5) unsigned NOT NULL default '0', PRIMARY KEY (`capfa_child`,`capfa_parent`,`relatta`) -) ENGINE=myisam DEFAULT CHARSET=latin1; -INSERT INTO `t6` VALUES (15,16,0),(19,20,0),(18326932092909551615,30,0),(26,29,0),(18326932092909551615,29,0),(19,18,0),(26,28,0),(12,14,0); +) ENGINE=ndbcluster DEFAULT CHARSET=latin1; +INSERT INTO `t6_c` VALUES (15,16,0),(19,20,0),(18326932092909551615,30,0),(26,29,0),(18326932092909551615,29,0),(19,18,0),(26,28,0),(12,14,0); -CREATE TABLE `t7` ( +# Bug #27775 - mediumint auto inc not restored correctly +# - check tinyint +CREATE TABLE `t7_c` ( `dardpo` char(15) NOT NULL default '', - `dardtestard` tinyint(3) unsigned NOT NULL default '0', + `dardtestard` tinyint(3) unsigned NOT NULL auto_increment, `FastFA` char(5) NOT NULL default '', `FastCode` char(6) NOT NULL default '', `Fastca` char(1) NOT NULL default '', `Fastmag` char(1) NOT NULL default '', `Beareratta` char(2) NOT NULL default '', PRIMARY KEY (`dardpo`,`dardtestard`) -) ENGINE=myisam DEFAULT CHARSET=latin1; -INSERT INTO `t7` VALUES ('2.6.2.4',24,'CECHP','54545','0','0','5'),('2.2.5.4',26,'CANFA','33223','1','1','4'),('4.3.2.4',28,'ITALD','54222','1','0','5'),('129..0.0.eins',28,'G','99999','1','1','5'),('1.1.1.1',24,'AUTPT','32323','0','1','3'); +) ENGINE=ndbcluster DEFAULT CHARSET=latin1; +INSERT INTO `t7_c` VALUES ('2.6.2.4',24,'CECHP','54545','0','0','5'),('2.2.5.4',26,'CANFA','33223','1','1','4'),('4.3.2.4',28,'ITALD','54222','1','0','5'),('129..0.0.eins',28,'G','99999','1','1','5'),('1.1.1.1',24,'AUTPT','32323','0','1','3'); -CREATE TABLE `t8` ( +CREATE TABLE `t8_c` ( `kattjame` varchar(32) NOT NULL default '', `realm` varchar(32) NOT NULL default '', `realm_entered` varchar(32) NOT NULL default '', @@ -102,10 +113,10 @@ CREATE TABLE `t8` ( `acctinputoctets` bigint(20) unsigned default NULL, PRIMARY KEY (`kattjame`,`hunderaaarbagefa`,`hassetistart`,`hassetino`), KEY `squardporoot` (`squardporoot`) -) ENGINE=myisam DEFAULT CHARSET=latin1; -INSERT INTO `t8` VALUES ('4tt45345235','pap','q3plus.qt','q3plus.qt','q3.net','436643196120','436643196929','8956234534568968','5524595699','uxasmt21.net.acne.qt/481889229462692422','','1.1.1.1','2.2.4.6','4','86989','34','x','x','2012-03-12 12:55:34','2012-12-05 11:20:04',3223433,3369,9565),('4545435545','john','q3.net','q3.net','acne.li','436643196120','436643196929','45345234568968','995696699','uxasmt21.net.acne.qt/481889229462692423','','1.1.1.1','2.2.9.8','2','86989','34','x','x','2012-03-12 11:35:03','2012-12-05 08:50:04',8821923,169,3565),('versteckter_q3net_katt','joe','q3.net','elredun.com','q3.net','436643196120','436643196939','91341234568968','695595699','uxasmt21.net.acne.qt/481889229462692421','','1.1.1.1','2.5.2.5','3','86989','34','x','x','2012-03-12 18:35:04','2012-12-05 12:35:04',1923123,9569,6565); +) ENGINE=ndbcluster DEFAULT CHARSET=latin1; +INSERT INTO `t8_c` VALUES ('4tt45345235','pap','q3plus.qt','q3plus.qt','q3.net','436643196120','436643196929','8956234534568968','5524595699','uxasmt21.net.acne.qt/481889229462692422','','1.1.1.1','2.2.4.6','4','86989','34','x','x','2012-03-12 12:55:34','2012-12-05 11:20:04',3223433,3369,9565),('4545435545','john','q3.net','q3.net','acne.li','436643196120','436643196929','45345234568968','995696699','uxasmt21.net.acne.qt/481889229462692423','','1.1.1.1','2.2.9.8','2','86989','34','x','x','2012-03-12 11:35:03','2012-12-05 08:50:04',8821923,169,3565),('versteckter_q3net_katt','joe','q3.net','elredun.com','q3.net','436643196120','436643196939','91341234568968','695595699','uxasmt21.net.acne.qt/481889229462692421','','1.1.1.1','2.5.2.5','3','86989','34','x','x','2012-03-12 18:35:04','2012-12-05 12:35:04',1923123,9569,6565); -CREATE TABLE `t9` ( +CREATE TABLE `t9_c` ( `kattjame` varchar(32) NOT NULL default '', `kattjame_entered` varchar(32) NOT NULL default '', `realm` varchar(32) NOT NULL default '', @@ -129,26 +140,29 @@ CREATE TABLE `t9` ( `actinputocctets` bigint(20) unsigned default NULL, `terminateraste` tinyint(3) unsigned default NULL, PRIMARY KEY (`kattjame`,`hunderaaarbagefa`,`hassetistart`,`hassetino`) -) ENGINE=myisam DEFAULT CHARSET=latin1; -INSERT INTO `t9` VALUES ('3g4jh8gar2t','joe','q3.net','elredun.com','q3.net','436643316120','436643316939','91341234568968','695595699','1.1.1.1','2.2.6.2','3','86989','34','x','x','2012-03-12 18:35:04','2012-12-05 12:35:04',3123123,9569,6565,1),('4tt45345235','pap','q3plus.qt','q3plus.qt','q3.net','436643316120','436643316939','8956234534568968','5254595969','1.1.1.1','8.6.2.2','4','86989','34','x','x','2012-03-12 12:55:34','2012-12-05 11:20:04',3223433,3369,9565,2),('4545435545','john','q3.net','q3.net','acne.li','436643316120','436643316939','45345234568968','995696699','1.1.1.1','2.9.9.2','2','86998','34','x','x','2012-03-12 11:35:03','2012-12-05 08:50:04',8823123,169,3565,3); +) ENGINE=ndbcluster DEFAULT CHARSET=latin1; +INSERT INTO `t9_c` VALUES ('3g4jh8gar2t','joe','q3.net','elredun.com','q3.net','436643316120','436643316939','91341234568968','695595699','1.1.1.1','2.2.6.2','3','86989','34','x','x','2012-03-12 18:35:04','2012-12-05 12:35:04',3123123,9569,6565,1),('4tt45345235','pap','q3plus.qt','q3plus.qt','q3.net','436643316120','436643316939','8956234534568968','5254595969','1.1.1.1','8.6.2.2','4','86989','34','x','x','2012-03-12 12:55:34','2012-12-05 11:20:04',3223433,3369,9565,2),('4545435545','john','q3.net','q3.net','acne.li','436643316120','436643316939','45345234568968','995696699','1.1.1.1','2.9.9.2','2','86998','34','x','x','2012-03-12 11:35:03','2012-12-05 08:50:04',8823123,169,3565,3); # Bug #20820 # auto inc table not handled correctly when restored from cluster backup # - before fix ndb_restore would not set auto inc value correct, # seen by select below -create table t10 (a int auto_increment key); -insert into t10 values (1),(2),(3); +create table t10_c (a int auto_increment key) ENGINE=ndbcluster; +insert into t10_c values (1),(2),(3); +# Bug #27775 - mediumint auto inc not restored correctly +# - check int +insert into t10_c values (10000),(2000),(3000); -create table t1_c engine=ndbcluster as select * from t1; -create table t2_c engine=ndbcluster as select * from t2; -create table t3_c engine=ndbcluster as select * from t3; -create table t4_c engine=ndbcluster as select * from t4; -create table t5_c engine=ndbcluster as select * from t5; -create table t6_c engine=ndbcluster as select * from t6; -create table t7_c engine=ndbcluster as select * from t7; -create table t8_c engine=ndbcluster as select * from t8; -create table t9_c engine=ndbcluster as select * from t9; -create table t10_c engine=ndbcluster as select * from t10; +create table t1 engine=myisam as select * from t1_c; +create table t2 engine=myisam as select * from t2_c; +create table t3 engine=myisam as select * from t3_c; +create table t4 engine=myisam as select * from t4_c; +create table t5 engine=myisam as select * from t5_c; +create table t6 engine=myisam as select * from t6_c; +create table t7 engine=myisam as select * from t7_c; +create table t8 engine=myisam as select * from t8_c; +create table t9 engine=myisam as select * from t9_c; +create table t10 engine=myisam as select * from t10_c; --exec $NDB_MGM --no-defaults -e "start backup" >> $NDB_TOOLS_OUTPUT @@ -215,6 +229,18 @@ select count(*) # Bug #20820 cont'd select * from t10_c order by a; +# Bug #27775 cont'd +# - auto inc info should be correct +--replace_column 1 X 2 X 3 X 4 X 5 X 6 X 7 X 8 X 9 X 10 X 12 X 13 X 14 X 15 X 16 X 17 X 18 X +show table status like 't1_c'; +--replace_column 1 X 2 X 3 X 4 X 5 X 6 X 7 X 8 X 9 X 10 X 12 X 13 X 14 X 15 X 16 X 17 X 18 X +show table status like 't2_c'; +--replace_column 1 X 2 X 3 X 4 X 5 X 6 X 7 X 8 X 9 X 10 X 12 X 13 X 14 X 15 X 16 X 17 X 18 X +show table status like 't4_c'; +--replace_column 1 X 2 X 3 X 4 X 5 X 6 X 7 X 8 X 9 X 10 X 12 X 13 X 14 X 15 X 16 X 17 X 18 X +show table status like 't7_c'; +--replace_column 1 X 2 X 3 X 4 X 5 X 6 X 7 X 8 X 9 X 10 X 12 X 13 X 14 X 15 X 16 X 17 X 18 X +show table status like 't10_c'; --disable_warnings drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9, t10; diff --git a/mysql-test/t/row.test b/mysql-test/t/row.test index 1d5c7a543ea..bf25359b7be 100644 --- a/mysql-test/t/row.test +++ b/mysql-test/t/row.test @@ -85,6 +85,31 @@ drop table t1; SELECT ROW(2,10) <=> ROW(3,4); SELECT ROW(NULL,10) <=> ROW(3,NULL); +# +# Bug #27484: nested row expressions in IN predicate +# + +--error 1241 +SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),ROW(1,1)); +--error 1241 +SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),ROW(1,1),ROW(1,ROW(2,3))); +--error 1241 +SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),ROW(1,ROW(2,2,2))); +--error 1241 +SELECT ROW(1,ROW(2,3,4)) IN (ROW(1,ROW(2,3,4)),ROW(1,ROW(2,2))); + +--error 1241 +SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),(SELECT 1,1)); +--error 1241 +SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),(SELECT 1,1),ROW(1,ROW(2,4))); +--error 1241 +SELECT ROW(1,ROW(2,3)) IN ((SELECT 1,1),ROW(1,ROW(2,3))); + +--error 1241 +SELECT ROW(2,1) IN (ROW(21,2),ROW(ROW(1,1,3),0)); +--error 1241 +SELECT ROW(2,1) IN (ROW(ROW(1,1,3),0),ROW(21,2)); + # End of 4.1 tests # diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index c5c7d07ee25..56b2f1b02b8 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -3357,4 +3357,17 @@ SELECT t2.faq_id DROP TABLE t1,t2; + +# +# Bug #19372: Optimizer does not use index anymore when WHERE index NOT IN +# () is added +# +CREATE TABLE t1 (a INT, b INT, KEY inx (b,a)); + +INSERT INTO t1 VALUES (1,1), (1,2), (1,3), (1,4), (1,5), (1, 6), (1,7); +EXPLAIN SELECT COUNT(*) FROM t1 f1 INNER JOIN t1 f2 + ON ( f1.b=f2.b AND f1.a (SELECT MAX(t2.b) FROM t2 WHERE t2.c < t1.c HAVING MAX(t2.b+t1.a) < 10)); -#FIXME: Enable this test after fixing bug #27321 -#SELECT a, AVG(b), (SELECT t.c FROM t1 AS t WHERE t1.a=t.a AND t.b=AVG(t1.b)) -# AS test FROM t1 GROUP BY a; SELECT a,b,c FROM t1 WHERE b in (9,3,4) ORDER BY b,c; diff --git a/mysql-test/t/truncate.test b/mysql-test/t/truncate.test index f806bd8ec17..c52260124cb 100644 --- a/mysql-test/t/truncate.test +++ b/mysql-test/t/truncate.test @@ -52,3 +52,35 @@ SELECT * from t1; drop table t1; # End of 4.1 tests + +# Test for Bug#5507 "TRUNCATE should work with views" + +create table t1 (s1 int); + +insert into t1 (s1) values (1), (2), (3), (4), (5); +create view v1 as select * from t1; +truncate table v1; +select count(*) from t1; + +insert into t1 (s1) values (1), (2), (3), (4), (5); +create view v2 as select * from t1 where s1 > 3; +truncate table v2; +select * from t1; +select * from v2; +delete from t1; + +# The following should fail +create table t2 (s1 int, s2 int); +create view v3 as select a.s1, b.s2 from t1 a join t2 b on a.s1 = b.s1 where a.s1 > 3; +--error 1395 +truncate table v3; + +# The following should fail +create view v4 as select * from t1 limit 1,1; +--error 1288 +truncate table v4; + +drop view v1, v2, v3, v4; +drop table t1, t2; + +# End of 5.0 tests diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 1b229298896..920fcee3b24 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -2228,6 +2228,8 @@ REPAIR TABLE v1; DROP TABLE t1; OPTIMIZE TABLE v1; +ANALYZE TABLE v1; +REPAIR TABLE v1; DROP VIEW v1; diff --git a/ndb/include/ndbapi/Ndb.hpp b/ndb/include/ndbapi/Ndb.hpp index 516333d1834..5af86cd09a8 100644 --- a/ndb/include/ndbapi/Ndb.hpp +++ b/ndb/include/ndbapi/Ndb.hpp @@ -1051,6 +1051,18 @@ class Ndb friend class NdbDictionaryImpl; friend class NdbDictInterface; friend class NdbBlob; + friend class Ndb_free_list_t; + friend class Ndb_free_list_t; + friend class Ndb_free_list_t; + friend class Ndb_free_list_t; + friend class Ndb_free_list_t; + friend class Ndb_free_list_t; + friend class Ndb_free_list_t; + friend class Ndb_free_list_t; + friend class Ndb_free_list_t; + friend class Ndb_free_list_t; + friend class Ndb_free_list_t; + friend class Ndb_free_list_t; #endif public: @@ -1091,7 +1103,7 @@ public: * * @param aCatalogName is the new name of the current catalog */ - void setCatalogName(const char * aCatalogName); + int setCatalogName(const char * aCatalogName); /** * The current schema name can be fetched by getSchemaName. @@ -1105,7 +1117,7 @@ public: * * @param aSchemaName is the new name of the current schema */ - void setSchemaName(const char * aSchemaName); + int setSchemaName(const char * aSchemaName); #endif /** @@ -1120,7 +1132,7 @@ public: * * @param aDatabaseName is the new name of the current database */ - void setDatabaseName(const char * aDatabaseName); + int setDatabaseName(const char * aDatabaseName); /** * The current database schema name can be fetched by getDatabaseSchemaName. @@ -1134,7 +1146,7 @@ public: * * @param aDatabaseSchemaName is the new name of the current database schema */ - void setDatabaseSchemaName(const char * aDatabaseSchemaName); + int setDatabaseSchemaName(const char * aDatabaseSchemaName); /** * Initializes the Ndb object diff --git a/ndb/include/ndbapi/NdbDictionary.hpp b/ndb/include/ndbapi/NdbDictionary.hpp index 34686dd4db1..445bb513ffc 100644 --- a/ndb/include/ndbapi/NdbDictionary.hpp +++ b/ndb/include/ndbapi/NdbDictionary.hpp @@ -358,7 +358,7 @@ public: * Set name of column * @param name Name of the column */ - void setName(const char * name); + int setName(const char * name); /** * Set whether column is nullable or not @@ -446,7 +446,7 @@ public: void setAutoIncrement(bool); bool getAutoIncrement() const; void setAutoIncrementInitialValue(Uint64 val); - void setDefaultValue(const char*); + int setDefaultValue(const char*); const char* getDefaultValue() const; static const Column * FRAGMENT; @@ -661,13 +661,13 @@ public: * Name of table * @param name Name of table */ - void setName(const char * name); + int setName(const char * name); /** * Add a column definition to a table * @note creates a copy */ - void addColumn(const Column &); + int addColumn(const Column &); /** * @see NdbDictionary::Table::getLogging. @@ -723,7 +723,7 @@ public: /** * Set frm file to store with this table */ - void setFrm(const void* data, Uint32 len); + int setFrm(const void* data, Uint32 len); /** * Set table object type @@ -875,26 +875,26 @@ public: /** * Set the name of an index */ - void setName(const char * name); + int setName(const char * name); /** * Define the name of the table to be indexed */ - void setTable(const char * name); + int setTable(const char * name); /** * Add a column to the index definition * Note that the order of columns will be in * the order they are added (only matters for ordered indexes). */ - void addColumn(const Column & c); + int addColumn(const Column & c); /** * Add a column name to the index definition * Note that the order of indexes will be in * the order they are added (only matters for ordered indexes). */ - void addColumnName(const char * name); + int addColumnName(const char * name); #ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED /** @@ -903,7 +903,7 @@ public: * the order they are added (only matters for ordered indexes). * Depricated, use addColumnName instead. */ - void addIndexColumn(const char * name); + int addIndexColumn(const char * name); #endif /** @@ -911,7 +911,7 @@ public: * Note that the order of indexes will be in * the order they are added (only matters for ordered indexes). */ - void addColumnNames(unsigned noOfNames, const char ** names); + int addColumnNames(unsigned noOfNames, const char ** names); #ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED /** @@ -920,7 +920,7 @@ public: * the order they are added (only matters for ordered indexes). * Depricated, use addColumnNames instead. */ - void addIndexColumns(int noOfNames, const char ** names); + int addIndexColumns(int noOfNames, const char ** names); #endif /** diff --git a/ndb/include/ndbapi/NdbRecAttr.hpp b/ndb/include/ndbapi/NdbRecAttr.hpp index 7f8add774dc..f5777cdddb3 100644 --- a/ndb/include/ndbapi/NdbRecAttr.hpp +++ b/ndb/include/ndbapi/NdbRecAttr.hpp @@ -332,13 +332,6 @@ NdbRecAttr::int32_value() const return *(Int32*)theRef; } -inline -Int32 -NdbRecAttr::medium_value() const -{ - return sint3korr((unsigned char *)theRef); -} - inline short NdbRecAttr::short_value() const @@ -360,13 +353,6 @@ NdbRecAttr::u_32_value() const return *(Uint32*)theRef; } -inline -Uint32 -NdbRecAttr::u_medium_value() const -{ - return uint3korr((unsigned char*)theRef); -} - inline Uint16 NdbRecAttr::u_short_value() const diff --git a/ndb/include/ndbapi/NdbReceiver.hpp b/ndb/include/ndbapi/NdbReceiver.hpp index 0af55c88f68..b8abd281496 100644 --- a/ndb/include/ndbapi/NdbReceiver.hpp +++ b/ndb/include/ndbapi/NdbReceiver.hpp @@ -38,7 +38,7 @@ public: }; NdbReceiver(Ndb *aNdb); - void init(ReceiverType type, void* owner); + int init(ReceiverType type, void* owner); void release(); ~NdbReceiver(); @@ -75,7 +75,7 @@ private: * At setup */ class NdbRecAttr * getValue(const class NdbColumnImpl*, char * user_dst_ptr); - void do_get_value(NdbReceiver*, Uint32 rows, Uint32 key_size, Uint32 range); + int do_get_value(NdbReceiver*, Uint32 rows, Uint32 key_size, Uint32 range); void prepareSend(); void calculate_batch_size(Uint32, Uint32, Uint32&, Uint32&, Uint32&); diff --git a/ndb/include/ndbapi/NdbTransaction.hpp b/ndb/include/ndbapi/NdbTransaction.hpp index 1a9c7158adf..d3405633f80 100644 --- a/ndb/include/ndbapi/NdbTransaction.hpp +++ b/ndb/include/ndbapi/NdbTransaction.hpp @@ -585,7 +585,7 @@ private: NdbTransaction(Ndb* aNdb); ~NdbTransaction(); - void init(); // Initialize connection object for new transaction + int init(); // Initialize connection object for new transaction int executeNoBlobs(ExecType execType, AbortOption abortOption = AbortOnError, diff --git a/ndb/include/util/BaseString.hpp b/ndb/include/util/BaseString.hpp index 44e1e4614be..34ca2d2be3d 100644 --- a/ndb/include/util/BaseString.hpp +++ b/ndb/include/util/BaseString.hpp @@ -185,6 +185,7 @@ public: private: char* m_chr; unsigned m_len; + friend bool operator!(const BaseString& str); }; inline const char* @@ -249,6 +250,12 @@ BaseString::operator!=(const char *str) const return strcmp(m_chr, str) != 0; } +inline bool +operator!(const BaseString& str) +{ + return str.m_chr == NULL; +} + inline BaseString& BaseString::assign(const BaseString& str) { diff --git a/ndb/include/util/Vector.hpp b/ndb/include/util/Vector.hpp index aeddbbb22f0..8f403b435dd 100644 --- a/ndb/include/util/Vector.hpp +++ b/ndb/include/util/Vector.hpp @@ -29,14 +29,14 @@ public: const T& operator[](unsigned i) const; unsigned size() const { return m_size; }; - void push_back(const T &); + int push_back(const T &); T& back(); void erase(unsigned index); void clear(); - void fill(unsigned new_size, T & obj); + int fill(unsigned new_size, T & obj); Vector& operator=(const Vector&); @@ -52,6 +52,14 @@ private: template Vector::Vector(int i){ m_items = new T[i]; + if (m_items == NULL) + { + errno = ENOMEM; + m_size = 0; + m_arraySize = 0; + m_incSize = 0; + return; + } m_size = 0; m_arraySize = i; m_incSize = 50; @@ -89,12 +97,15 @@ Vector::back(){ } template -void +int Vector::push_back(const T & t){ if(m_size == m_arraySize){ T * tmp = new T [m_arraySize + m_incSize]; - if(!tmp) - abort(); + if(tmp == NULL) + { + errno = ENOMEM; + return -1; + } for (unsigned k = 0; k < m_size; k++) tmp[k] = m_items[k]; delete[] m_items; @@ -103,6 +114,8 @@ Vector::push_back(const T & t){ } m_items[m_size] = t; m_size++; + + return 0; } template @@ -123,10 +136,12 @@ Vector::clear(){ } template -void +int Vector::fill(unsigned new_size, T & obj){ while(m_size <= new_size) - push_back(obj); + if (push_back(obj)) + return -1; + return 0; } template @@ -150,8 +165,8 @@ struct MutexVector : public NdbLockable { const T& operator[](unsigned i) const; unsigned size() const { return m_size; }; - void push_back(const T &); - void push_back(const T &, bool lockMutex); + int push_back(const T &); + int push_back(const T &, bool lockMutex); T& back(); void erase(unsigned index); @@ -160,7 +175,7 @@ struct MutexVector : public NdbLockable { void clear(); void clear(bool lockMutex); - void fill(unsigned new_size, T & obj); + int fill(unsigned new_size, T & obj); private: T * m_items; unsigned m_size; @@ -171,6 +186,14 @@ private: template MutexVector::MutexVector(int i){ m_items = new T[i]; + if (m_items == NULL) + { + errno = ENOMEM; + m_size = 0; + m_arraySize = 0; + m_incSize = 0; + return; + } m_size = 0; m_arraySize = i; m_incSize = 50; @@ -208,11 +231,17 @@ MutexVector::back(){ } template -void +int MutexVector::push_back(const T & t){ lock(); if(m_size == m_arraySize){ T * tmp = new T [m_arraySize + m_incSize]; + if (tmp == NULL) + { + errno = ENOMEM; + unlock(); + return -1; + } for (unsigned k = 0; k < m_size; k++) tmp[k] = m_items[k]; delete[] m_items; @@ -222,15 +251,23 @@ MutexVector::push_back(const T & t){ m_items[m_size] = t; m_size++; unlock(); + return 0; } template -void +int MutexVector::push_back(const T & t, bool lockMutex){ if(lockMutex) lock(); if(m_size == m_arraySize){ T * tmp = new T [m_arraySize + m_incSize]; + if (tmp == NULL) + { + errno = ENOMEM; + if(lockMutex) + unlock(); + return -1; + } for (unsigned k = 0; k < m_size; k++) tmp[k] = m_items[k]; delete[] m_items; @@ -241,6 +278,7 @@ MutexVector::push_back(const T & t, bool lockMutex){ m_size++; if(lockMutex) unlock(); + return 0; } template @@ -288,10 +326,12 @@ MutexVector::clear(bool l){ } template -void +int MutexVector::fill(unsigned new_size, T & obj){ while(m_size <= new_size) - push_back(obj); + if (push_back(obj)) + return -1; + return 0; } #endif diff --git a/ndb/src/common/util/BaseString.cpp b/ndb/src/common/util/BaseString.cpp index 6f20ae6a002..7e5adf0e9ef 100644 --- a/ndb/src/common/util/BaseString.cpp +++ b/ndb/src/common/util/BaseString.cpp @@ -16,19 +16,36 @@ /* -*- c-basic-offset: 4; -*- */ #include #include -#include +#include "basestring_vsnprintf.h" BaseString::BaseString() { m_chr = new char[1]; + if (m_chr == NULL) + { + errno = ENOMEM; + m_len = 0; + return; + } m_chr[0] = 0; m_len = 0; } BaseString::BaseString(const char* s) { + if (s == NULL) + { + m_chr = NULL; + m_len = 0; + } const size_t n = strlen(s); m_chr = new char[n + 1]; + if (m_chr == NULL) + { + errno = ENOMEM; + m_len = 0; + return; + } memcpy(m_chr, s, n + 1); m_len = n; } @@ -37,7 +54,20 @@ BaseString::BaseString(const BaseString& str) { const char* const s = str.m_chr; const size_t n = str.m_len; + if (s == NULL) + { + m_chr = NULL; + m_len = 0; + return; + } char* t = new char[n + 1]; + if (t == NULL) + { + errno = ENOMEM; + m_chr = NULL; + m_len = 0; + return; + } memcpy(t, s, n + 1); m_chr = t; m_len = n; @@ -51,9 +81,23 @@ BaseString::~BaseString() BaseString& BaseString::assign(const char* s) { - const size_t n = strlen(s); + if (s == NULL) + { + m_chr = NULL; + m_len = 0; + return *this; + } + size_t n = strlen(s); char* t = new char[n + 1]; - memcpy(t, s, n + 1); + if (t) + { + memcpy(t, s, n + 1); + } + else + { + errno = ENOMEM; + n = 0; + } delete[] m_chr; m_chr = t; m_len = n; @@ -64,8 +108,16 @@ BaseString& BaseString::assign(const char* s, size_t n) { char* t = new char[n + 1]; - memcpy(t, s, n); - t[n] = 0; + if (t) + { + memcpy(t, s, n); + t[n] = 0; + } + else + { + errno = ENOMEM; + n = 0; + } delete[] m_chr; m_chr = t; m_len = n; @@ -83,10 +135,19 @@ BaseString::assign(const BaseString& str, size_t n) BaseString& BaseString::append(const char* s) { - const size_t n = strlen(s); + size_t n = strlen(s); char* t = new char[m_len + n + 1]; - memcpy(t, m_chr, m_len); - memcpy(t + m_len, s, n + 1); + if (t) + { + memcpy(t, m_chr, m_len); + memcpy(t + m_len, s, n + 1); + } + else + { + errno = ENOMEM; + m_len = 0; + n = 0; + } delete[] m_chr; m_chr = t; m_len += n; @@ -130,8 +191,14 @@ BaseString::assfmt(const char *fmt, ...) l = basestring_vsnprintf(buf, sizeof(buf), fmt, ap) + 1; va_end(ap); if(l > (int)m_len) { + char *t = new char[l]; + if (t == NULL) + { + errno = ENOMEM; + return *this; + } delete[] m_chr; - m_chr = new char[l]; + m_chr = t; } va_start(ap, fmt); basestring_vsnprintf(m_chr, l, fmt, ap); @@ -155,6 +222,11 @@ BaseString::appfmt(const char *fmt, ...) l = basestring_vsnprintf(buf, sizeof(buf), fmt, ap) + 1; va_end(ap); char *tmp = new char[l]; + if (tmp == NULL) + { + errno = ENOMEM; + return *this; + } va_start(ap, fmt); basestring_vsnprintf(tmp, l, fmt, ap); va_end(ap); @@ -242,9 +314,28 @@ BaseString::argify(const char *argv0, const char *src) { Vector vargv; if(argv0 != NULL) - vargv.push_back(strdup(argv0)); + { + char *t = strdup(argv0); + if (t == NULL) + { + errno = ENOMEM; + return NULL; + } + if (vargv.push_back(t)) + { + free(t); + return NULL; + } + } char *tmp = new char[strlen(src)+1]; + if (tmp == NULL) + { + for(size_t i = 0; i < vargv.size(); i++) + free(vargv[i]); + errno = ENOMEM; + return NULL; + } char *dst = tmp; const char *end = src + strlen(src); /* Copy characters from src to destination, while compacting them @@ -287,20 +378,48 @@ BaseString::argify(const char *argv0, const char *src) { /* Make sure the string is properly terminated */ *dst++ = '\0'; src++; - - vargv.push_back(strdup(begin)); + + { + char *t = strdup(begin); + if (t == NULL) + { + delete[] tmp; + for(size_t i = 0; i < vargv.size(); i++) + free(vargv[i]); + errno = ENOMEM; + return NULL; + } + if (vargv.push_back(t)) + { + free(t); + delete[] tmp; + for(size_t i = 0; i < vargv.size(); i++) + free(vargv[i]); + return NULL; + } + } } end: delete[] tmp; - vargv.push_back(NULL); + if (vargv.push_back(NULL)) + { + for(size_t i = 0; i < vargv.size(); i++) + free(vargv[i]); + return NULL; + } /* Convert the C++ Vector into a C-vector of strings, suitable for * calling execv(). */ char **argv = (char **)malloc(sizeof(*argv) * (vargv.size())); if(argv == NULL) + { + for(size_t i = 0; i < vargv.size(); i++) + free(vargv[i]); + errno = ENOMEM; return NULL; + } for(size_t i = 0; i < vargv.size(); i++){ argv[i] = vargv[i]; diff --git a/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp b/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp index 017b0ec5b92..71cfa98b68b 100644 --- a/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp +++ b/ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp @@ -389,6 +389,7 @@ Dbtup::commitRecord(Signal* signal, fragptr.p = regFragPtr; tabptr.p = regTabPtr; + Uint32 hashValue = firstOpPtr.p->hashValue; if (opType == ZINSERT_DELETE) { ljam(); @@ -411,6 +412,7 @@ Dbtup::commitRecord(Signal* signal, //-------------------------------------------------------------------- Uint32 saveOpType = regOperPtr->optype; regOperPtr->optype = ZINSERT; + regOperPtr->hashValue = hashValue; operPtr.p = regOperPtr; checkDetachedTriggers(signal, @@ -443,6 +445,8 @@ Dbtup::commitRecord(Signal* signal, befOpPtr.p->changeMask.clear(); befOpPtr.p->changeMask.bitOR(attributeMask); befOpPtr.p->gci = regOperPtr->gci; + befOpPtr.p->optype = ZUPDATE; + befOpPtr.p->hashValue = hashValue; befOpPtr.p->optype = opType; operPtr.p = befOpPtr.p; @@ -477,11 +481,13 @@ Dbtup::commitRecord(Signal* signal, Uint32 fragPageId = befOpPtr.p->fragPageId; Uint32 pageIndex = befOpPtr.p->pageIndex; + befOpPtr.p->optype = ZDELETE; befOpPtr.p->realPageId = befOpPtr.p->realPageIdC; befOpPtr.p->pageOffset = befOpPtr.p->pageOffsetC; befOpPtr.p->fragPageId = befOpPtr.p->fragPageIdC; befOpPtr.p->pageIndex = befOpPtr.p->pageIndexC; befOpPtr.p->gci = regOperPtr->gci; + befOpPtr.p->hashValue = hashValue; befOpPtr.p->optype = opType; operPtr.p = befOpPtr.p; diff --git a/ndb/src/ndbapi/DictCache.cpp b/ndb/src/ndbapi/DictCache.cpp index 82e8d82bc24..6a815067233 100644 --- a/ndb/src/ndbapi/DictCache.cpp +++ b/ndb/src/ndbapi/DictCache.cpp @@ -141,7 +141,7 @@ void GlobalDictCache::printCache() } NdbTableImpl * -GlobalDictCache::get(const char * name) +GlobalDictCache::get(const char * name, int *error) { DBUG_ENTER("GlobalDictCache::get"); DBUG_PRINT("enter", ("name: %s", name)); @@ -151,6 +151,11 @@ GlobalDictCache::get(const char * name) versions = m_tableHash.getData(name, len); if(versions == 0){ versions = new Vector(2); + if (versions == NULL) + { + *error = -1; + DBUG_RETURN(0); + } m_tableHash.insertKey(name, len, 0, versions); } @@ -180,7 +185,11 @@ GlobalDictCache::get(const char * name) tmp.m_impl = 0; tmp.m_status = RETREIVING; tmp.m_refCount = 1; // The one retreiving it - versions->push_back(tmp); + if (versions->push_back(tmp)) + { + *error = -1; + DBUG_RETURN(0); + } DBUG_RETURN(0); } diff --git a/ndb/src/ndbapi/DictCache.hpp b/ndb/src/ndbapi/DictCache.hpp index 4b569c114c9..db90a07d487 100644 --- a/ndb/src/ndbapi/DictCache.hpp +++ b/ndb/src/ndbapi/DictCache.hpp @@ -67,7 +67,7 @@ public: GlobalDictCache(); ~GlobalDictCache(); - NdbTableImpl * get(const char * name); + NdbTableImpl * get(const char * name, int *error); NdbTableImpl* put(const char * name, NdbTableImpl *); void drop(NdbTableImpl *); diff --git a/ndb/src/ndbapi/Makefile.am b/ndb/src/ndbapi/Makefile.am index 85013b540dc..1a5d10eae5b 100644 --- a/ndb/src/ndbapi/Makefile.am +++ b/ndb/src/ndbapi/Makefile.am @@ -48,7 +48,8 @@ libndbapi_la_SOURCES = \ DictCache.cpp \ ndb_cluster_connection.cpp \ NdbBlob.cpp \ - SignalSender.cpp + SignalSender.cpp \ + ObjectMap.cpp INCLUDES_LOC = -I$(top_srcdir)/ndb/src/mgmapi diff --git a/ndb/src/ndbapi/Ndb.cpp b/ndb/src/ndbapi/Ndb.cpp index 57077559c49..449f287dc1d 100644 --- a/ndb/src/ndbapi/Ndb.cpp +++ b/ndb/src/ndbapi/Ndb.cpp @@ -182,6 +182,7 @@ Ndb::NDB_connect(Uint32 tNode) nodeSequence = tp->getNodeSequence(tNode); bool node_is_alive = tp->get_node_alive(tNode); if (node_is_alive) { + DBUG_PRINT("info",("Sending signal to node %u", tNode)); tReturnCode = tp->sendSignal(tSignal, tNode); releaseSignal(tSignal); if (tReturnCode != -1) { @@ -449,7 +450,11 @@ Ndb::startTransactionLocal(Uint32 aPriority, Uint32 nodeId) theRemainingStartTransactions--; NdbTransaction* tConNext = theTransactionList; - tConnection->init(); + if (tConnection->init()) + { + theError.code = tConnection->theError.code; + DBUG_RETURN(NULL); + } theTransactionList = tConnection; // into a transaction list. tConnection->next(tConNext); // Add the active connection object tConnection->setTransactionId(tFirstTransId); @@ -1129,28 +1134,37 @@ const char * Ndb::getCatalogName() const } -void Ndb::setCatalogName(const char * a_catalog_name) +int Ndb::setCatalogName(const char * a_catalog_name) { if (a_catalog_name) { - theImpl->m_dbname.assign(a_catalog_name); - theImpl->update_prefix(); + if (!theImpl->m_dbname.assign(a_catalog_name) || + theImpl->update_prefix()) + { + theError.code = 4000; + return -1; + } } + return 0; } - const char * Ndb::getSchemaName() const { return theImpl->m_schemaname.c_str(); } -void Ndb::setSchemaName(const char * a_schema_name) +int Ndb::setSchemaName(const char * a_schema_name) { if (a_schema_name) { - theImpl->m_schemaname.assign(a_schema_name); - theImpl->update_prefix(); + if (!theImpl->m_schemaname.assign(a_schema_name) || + theImpl->update_prefix()) + { + theError.code = 4000; + return -1; + } } + return 0; } /* @@ -1161,9 +1175,9 @@ const char * Ndb::getDatabaseName() const return getCatalogName(); } -void Ndb::setDatabaseName(const char * a_catalog_name) +int Ndb::setDatabaseName(const char * a_catalog_name) { - setCatalogName(a_catalog_name); + return setCatalogName(a_catalog_name); } const char * Ndb::getDatabaseSchemaName() const @@ -1171,9 +1185,9 @@ const char * Ndb::getDatabaseSchemaName() const return getSchemaName(); } -void Ndb::setDatabaseSchemaName(const char * a_schema_name) +int Ndb::setDatabaseSchemaName(const char * a_schema_name) { - setSchemaName(a_schema_name); + return setSchemaName(a_schema_name); } bool Ndb::usingFullyQualifiedNames() @@ -1287,6 +1301,11 @@ const BaseString Ndb::getDatabaseFromInternalName(const char * internalName) { char * databaseName = new char[strlen(internalName) + 1]; + if (databaseName == NULL) + { + errno = ENOMEM; + return BaseString(NULL); + } strcpy(databaseName, internalName); register char *ptr = databaseName; @@ -1303,6 +1322,11 @@ const BaseString Ndb::getSchemaFromInternalName(const char * internalName) { char * schemaName = new char[strlen(internalName)]; + if (schemaName == NULL) + { + errno = ENOMEM; + return BaseString(NULL); + } register const char *ptr1 = internalName; /* Scan name for the second table_name_separator */ diff --git a/ndb/src/ndbapi/NdbDictionary.cpp b/ndb/src/ndbapi/NdbDictionary.cpp index 0a52f62aa01..86a6624959e 100644 --- a/ndb/src/ndbapi/NdbDictionary.cpp +++ b/ndb/src/ndbapi/NdbDictionary.cpp @@ -52,9 +52,9 @@ NdbDictionary::Column::operator=(const NdbDictionary::Column& column) return *this; } -void +int NdbDictionary::Column::setName(const char * name){ - m_impl.m_name.assign(name); + return !m_impl.m_name.assign(name); } const char* @@ -208,10 +208,10 @@ NdbDictionary::Column::setAutoIncrementInitialValue(Uint64 val){ m_impl.m_autoIncrementInitialValue = val; } -void +int NdbDictionary::Column::setDefaultValue(const char* defaultValue) { - m_impl.m_defaultValue.assign(defaultValue); + return !m_impl.m_defaultValue.assign(defaultValue); } const char* @@ -273,9 +273,9 @@ NdbDictionary::Table::operator=(const NdbDictionary::Table& table) return *this; } -void +int NdbDictionary::Table::setName(const char * name){ - m_impl.setName(name); + return m_impl.setName(name); } const char * @@ -288,18 +288,30 @@ NdbDictionary::Table::getTableId() const { return m_impl.m_tableId; } -void +int NdbDictionary::Table::addColumn(const Column & c){ NdbColumnImpl* col = new NdbColumnImpl; + if (col == NULL) + { + errno = ENOMEM; + return -1; + } (* col) = NdbColumnImpl::getImpl(c); - m_impl.m_columns.push_back(col); + if (m_impl.m_columns.push_back(col)) + { + return -1; + } if(c.getPrimaryKey()){ m_impl.m_noOfKeys++; } if (col->getBlobType()) { m_impl.m_noOfBlobs++; } - m_impl.buildColumnHash(); + if (m_impl.buildColumnHash()) + { + return -1; + } + return 0; } const NdbDictionary::Column* @@ -442,9 +454,9 @@ NdbDictionary::Table::setSingleUserMode(enum NdbDictionary::Table::SingleUserMod m_impl.m_single_user_mode = (Uint8)mode; } -void +int NdbDictionary::Table::setFrm(const void* data, Uint32 len){ - m_impl.m_frm.assign(data, len); + return m_impl.m_frm.assign(data, len); } NdbDictionary::Object::Status @@ -491,6 +503,7 @@ NdbDictionary::Table::createTableInDb(Ndb* pNdb, bool equalOk) const { /***************************************************************** * Index facade */ + NdbDictionary::Index::Index(const char * name) : m_impl(* new NdbIndexImpl(* this)) { @@ -509,9 +522,9 @@ NdbDictionary::Index::~Index(){ } } -void +int NdbDictionary::Index::setName(const char * name){ - m_impl.setName(name); + return m_impl.setName(name); } const char * @@ -519,9 +532,9 @@ NdbDictionary::Index::getName() const { return m_impl.getName(); } -void +int NdbDictionary::Index::setTable(const char * table){ - m_impl.setTable(table); + return m_impl.setTable(table); } const char * @@ -556,39 +569,56 @@ NdbDictionary::Index::getIndexColumn(int no) const { return NULL; } -void +int NdbDictionary::Index::addColumn(const Column & c){ NdbColumnImpl* col = new NdbColumnImpl; + if (col == NULL) + { + errno = ENOMEM; + return -1; + } (* col) = NdbColumnImpl::getImpl(c); - m_impl.m_columns.push_back(col); + if (m_impl.m_columns.push_back(col)) + { + return -1; + } + return 0; } -void +int NdbDictionary::Index::addColumnName(const char * name){ const Column c(name); - addColumn(c); + return addColumn(c); } -void +int NdbDictionary::Index::addIndexColumn(const char * name){ const Column c(name); - addColumn(c); + return addColumn(c); } -void +int NdbDictionary::Index::addColumnNames(unsigned noOfNames, const char ** names){ for(unsigned i = 0; i < noOfNames; i++) { const Column c(names[i]); - addColumn(c); + if (addColumn(c)) + { + return -1; + } } + return 0; } -void +int NdbDictionary::Index::addIndexColumns(int noOfNames, const char ** names){ for(int i = 0; i < noOfNames; i++) { const Column c(names[i]); - addColumn(c); + if (addColumn(c)) + { + return -1; + } } + return 0; } void diff --git a/ndb/src/ndbapi/NdbDictionaryImpl.cpp b/ndb/src/ndbapi/NdbDictionaryImpl.cpp index 8604d50830d..3fed04de26d 100644 --- a/ndb/src/ndbapi/NdbDictionaryImpl.cpp +++ b/ndb/src/ndbapi/NdbDictionaryImpl.cpp @@ -390,22 +390,34 @@ NdbTableImpl::equal(const NdbTableImpl& obj) const DBUG_RETURN(true); } -void +int NdbTableImpl::assign(const NdbTableImpl& org) { m_tableId = org.m_tableId; - m_internalName.assign(org.m_internalName); - m_externalName.assign(org.m_externalName); - m_newExternalName.assign(org.m_newExternalName); - m_frm.assign(org.m_frm.get_data(), org.m_frm.length()); + if (!m_internalName.assign(org.m_internalName) || + !m_externalName.assign(org.m_externalName) || + !m_newExternalName.assign(org.m_newExternalName) || + m_frm.assign(org.m_frm.get_data(), org.m_frm.length())) + { + return -1; + } m_fragmentType = org.m_fragmentType; m_fragmentCount = org.m_fragmentCount; for(unsigned i = 0; i hashValues; - Vector > chains; chains.fill(size, hashValues); + Vector > chains; + if (chains.fill(size, hashValues)) + { + return -1; + } for(i = 0; i< (int) size; i++){ Uint32 hv = Hash(m_columns[i]->getName()) & 0xFFFE; Uint32 bucket = hv & m_columnHashMask; bucket = (bucket < size ? bucket : bucket - size); assert(bucket < size); - hashValues.push_back(hv); - chains[bucket].push_back(i); + if (hashValues.push_back(hv) || + chains[bucket].push_back(i)) + { + return -1; + } } m_columnHash.clear(); Uint32 tmp = 1; - m_columnHash.fill((unsigned)size-1, tmp); // Default no chaining + if (m_columnHash.fill((unsigned)size-1, tmp)) // Default no chaining + { + return -1; + } Uint32 pos = 0; // In overflow vector for(i = 0; i< (int) size; i++){ @@ -490,12 +514,18 @@ NdbTableImpl::buildColumnHash(){ for(size_t j = 0; j 0 ? m_columns[col]->getName() : "" , m_columnHash[i]); } #endif + return 0; } Uint32 @@ -563,9 +594,9 @@ NdbIndexImpl::~NdbIndexImpl(){ delete m_columns[i]; } -void NdbIndexImpl::setName(const char * name) +int NdbIndexImpl::setName(const char * name) { - m_externalName.assign(name); + return !m_externalName.assign(name); } const char * @@ -574,10 +605,10 @@ NdbIndexImpl::getName() const return m_externalName.c_str(); } -void +int NdbIndexImpl::setTable(const char * table) { - m_tableName.assign(table); + return !m_tableName.assign(table); } const char * @@ -657,14 +688,18 @@ Ndb_local_table_info * NdbDictionaryImpl::fetchGlobalTableImpl(const BaseString& internalTableName) { NdbTableImpl *impl; + int error= 0; m_globalHash->lock(); - impl = m_globalHash->get(internalTableName.c_str()); + impl = m_globalHash->get(internalTableName.c_str(), &error); m_globalHash->unlock(); if (impl == 0){ - impl = m_receiver.getTable(internalTableName, - m_ndb.usingFullyQualifiedNames()); + if (error == 0) + impl = m_receiver.getTable(internalTableName, + m_ndb.usingFullyQualifiedNames()); + else + m_error.code = 4000; m_globalHash->lock(); m_globalHash->put(internalTableName.c_str(), impl); m_globalHash->unlock(); @@ -998,12 +1033,20 @@ NdbDictInterface::getTable(const BaseString& name, bool fullyQualifiedNames) // Copy name to m_buffer to get a word sized buffer m_buffer.clear(); - m_buffer.grow(namelen_words*4+4); - m_buffer.append(name.c_str(), namelen); + if (m_buffer.grow(namelen_words*4+4) || + m_buffer.append(name.c_str(), namelen)) + { + m_error.code= 4000; + return NULL; + } #ifndef IGNORE_VALGRIND_WARNINGS Uint32 pad = 0; - m_buffer.append(&pad, 4); + if (m_buffer.append(&pad, 4)) + { + m_error.code= 4000; + return NULL; + } #endif LinearSectionPtr ptr[1]; @@ -1034,7 +1077,14 @@ NdbDictInterface::getTable(class NdbApiSignal * signal, (Uint32*)m_buffer.get_data(), m_buffer.length() / 4, fullyQualifiedNames); if (rt != 0) - rt->buildColumnHash(); + { + if (rt->buildColumnHash()) + { + m_error.code = 4000; + delete rt; + return NULL; + } + } return rt; } @@ -1043,18 +1093,25 @@ NdbDictInterface::execGET_TABINFO_CONF(NdbApiSignal * signal, LinearSectionPtr ptr[3]) { const GetTabInfoConf* conf = CAST_CONSTPTR(GetTabInfoConf, signal->getDataPtr()); + const Uint32 i = GetTabInfoConf::DICT_TAB_INFO; if(signal->isFirstFragment()){ m_fragmentId = signal->getFragmentId(); - m_buffer.grow(4 * conf->totalLen); + if (m_buffer.grow(4 * conf->totalLen)) + { + m_error.code= 4000; + goto end; + } } else { if(m_fragmentId != signal->getFragmentId()){ abort(); } } - const Uint32 i = GetTabInfoConf::DICT_TAB_INFO; - m_buffer.append(ptr[i].p, 4 * ptr[i].sz); - + if (m_buffer.append(ptr[i].p, 4 * ptr[i].sz)) + { + m_error.code= 4000; + } +end: if(!signal->isLastFragment()){ return; } @@ -1185,10 +1242,12 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret, impl->m_tableId = tableDesc.TableId; impl->m_version = tableDesc.TableVersion; impl->m_status = NdbDictionary::Object::Retrieved; - impl->m_internalName.assign(internalName); - impl->m_externalName.assign(externalName); - - impl->m_frm.assign(tableDesc.FrmData, tableDesc.FrmLen); + if (!impl->m_internalName.assign(internalName) || + !impl->m_externalName.assign(externalName) || + impl->m_frm.assign(tableDesc.FrmData, tableDesc.FrmLen)) + { + DBUG_RETURN(4000); + } impl->m_fragmentType = (NdbDictionary::Object::FragmentType) getApiConstant(tableDesc.FragmentType, @@ -1216,7 +1275,10 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret, } else { const char * externalPrimary = Ndb::externalizeTableName(tableDesc.PrimaryTable, fullyQualifiedNames); - impl->m_primaryTable.assign(externalPrimary); + if (!impl->m_primaryTable.assign(externalPrimary)) + { + DBUG_RETURN(4000); + } } Uint32 keyInfoPos = 0; @@ -1243,6 +1305,7 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret, // check type and compute attribute size and array size if (! attrDesc.translateExtType()) { + delete col; delete impl; DBUG_RETURN(703); } @@ -1254,12 +1317,14 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret, unsigned cs_number = (attrDesc.AttributeExtPrecision >> 16); // charset is defined exactly for char types if (col->getCharType() != (cs_number != 0)) { + delete col; delete impl; DBUG_RETURN(703); } if (col->getCharType()) { col->m_cs = get_charset(cs_number, MYF(0)); if (col->m_cs == NULL) { + delete col; delete impl; DBUG_RETURN(743); } @@ -1277,7 +1342,12 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret, col->m_nullable = attrDesc.AttributeNullableFlag; col->m_autoIncrement = (attrDesc.AttributeAutoIncrement ? true : false); col->m_autoIncrementInitialValue = ~0; - col->m_defaultValue.assign(attrDesc.AttributeDefaultValue); + if (!col->m_defaultValue.assign(attrDesc.AttributeDefaultValue)) + { + delete col; + delete impl; + DBUG_RETURN(4000); + } if(attrDesc.AttributeKeyFlag){ col->m_keyInfoPos = keyInfoPos + 1; @@ -1317,7 +1387,11 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret, for(i = 0; i<(fragCount*replicaCount); i++) { - impl->m_fragments.push_back(tableDesc.FragmentData[i+2]); + if (impl->m_fragments.push_back(tableDesc.FragmentData[i+2])) + { + delete impl; + DBUG_RETURN(4000); + } } Uint32 topBit = (1 << 31); @@ -1481,7 +1555,11 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb, } if (!impl.m_newExternalName.empty()) { - impl.m_externalName.assign(impl.m_newExternalName); + if (!impl.m_externalName.assign(impl.m_newExternalName)) + { + m_error.code= 4000; + DBUG_RETURN(-1); + } AlterTableReq::setNameFlag(impl.m_changeMask, true); } @@ -1490,7 +1568,11 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb, const BaseString internalName( ndb.internalize_table_name(impl.m_externalName.c_str())); - impl.m_internalName.assign(internalName); + if (!impl.m_internalName.assign(internalName)) + { + m_error.code= 4000; + DBUG_RETURN(-1); + } UtilBufferWriter w(m_buffer); DictTabInfo::Table tmpTab; tmpTab.init(); BaseString::snprintf(tmpTab.TableName, @@ -1967,13 +2049,19 @@ NdbDictionaryImpl::getIndexImpl(const char * externalName, NdbIndexImpl* idx; if(NdbDictInterface::create_index_obj_from_table(&idx, tab, prim) == 0){ idx->m_table = tab; - idx->m_externalName.assign(externalName); - idx->m_internalName.assign(internalName); + if (!idx->m_externalName.assign(externalName) || + !idx->m_internalName.assign(internalName)) + { + delete idx; + m_error.code = 4000; + return 0; + } // TODO Assign idx to tab->m_index // Don't do it right now since assign can't asign a table with index // tab->m_index = idx; return idx; } + m_error.code = 4000; return 0; } @@ -1982,11 +2070,21 @@ NdbDictInterface::create_index_obj_from_table(NdbIndexImpl** dst, NdbTableImpl* tab, const NdbTableImpl* prim){ NdbIndexImpl *idx = new NdbIndexImpl(); + if (idx == NULL) + { + errno = ENOMEM; + return -1; + } idx->m_version = tab->m_version; idx->m_status = tab->m_status; idx->m_indexId = tab->m_tableId; - idx->m_externalName.assign(tab->getName()); - idx->m_tableName.assign(prim->m_externalName); + if (!idx->m_externalName.assign(tab->getName()) || + !idx->m_tableName.assign(prim->m_externalName)) + { + delete idx; + errno = ENOMEM; + return -1; + } NdbDictionary::Index::Type type = idx->m_type = tab->m_indexType; idx->m_logging = tab->m_logging; // skip last attribute (NDB$PK or NDB$TNODE) @@ -1999,9 +2097,20 @@ NdbDictInterface::create_index_obj_from_table(NdbIndexImpl** dst, NdbColumnImpl* org = tab->m_columns[i]; NdbColumnImpl* col = new NdbColumnImpl; + if (col == NULL) + { + errno = ENOMEM; + delete idx; + return -1; + } // Copy column definition *col = * org; - idx->m_columns.push_back(col); + if (idx->m_columns.push_back(col)) + { + delete col; + delete idx; + return -1; + } /** * reverse map @@ -2067,7 +2176,11 @@ NdbDictInterface::createIndex(Ndb & ndb, } const BaseString internalName( ndb.internalize_index_name(&table, impl.getName())); - impl.m_internalName.assign(internalName); + if (!impl.m_internalName.assign(internalName)) + { + m_error.code = 4000; + return -1; + } w.add(DictTabInfo::TableName, internalName.c_str()); w.add(DictTabInfo::TableLoggedFlag, impl.m_logging); @@ -2353,34 +2466,72 @@ NdbDictInterface::listObjects(NdbDictionary::Dictionary::List& list, BaseString databaseName; BaseString schemaName; BaseString objectName; + if (!databaseName || !schemaName || !objectName) + { + m_error.code= 4000; + return -1; + } if ((element.type == NdbDictionary::Object::UniqueHashIndex) || (element.type == NdbDictionary::Object::OrderedIndex)) { char * indexName = new char[n << 2]; + if (indexName == NULL) + { + m_error.code= 4000; + return -1; + } memcpy(indexName, &data[pos], n << 2); - databaseName = Ndb::getDatabaseFromInternalName(indexName); - schemaName = Ndb::getSchemaFromInternalName(indexName); + if (!(databaseName = Ndb::getDatabaseFromInternalName(indexName)) || + !(schemaName = Ndb::getSchemaFromInternalName(indexName))) + { + delete [] indexName; + m_error.code= 4000; + return -1; + } objectName = BaseString(Ndb::externalizeIndexName(indexName, fullyQualifiedNames)); delete [] indexName; } else if ((element.type == NdbDictionary::Object::SystemTable) || (element.type == NdbDictionary::Object::UserTable)) { char * tableName = new char[n << 2]; + if (tableName == NULL) + { + m_error.code= 4000; + return -1; + } memcpy(tableName, &data[pos], n << 2); - databaseName = Ndb::getDatabaseFromInternalName(tableName); - schemaName = Ndb::getSchemaFromInternalName(tableName); + if (!(databaseName = Ndb::getDatabaseFromInternalName(tableName)) || + !(schemaName = Ndb::getSchemaFromInternalName(tableName))) + { + delete [] tableName; + m_error.code= 4000; + return -1; + } objectName = BaseString(Ndb::externalizeTableName(tableName, fullyQualifiedNames)); delete [] tableName; } else { char * otherName = new char[n << 2]; + if (otherName == NULL) + { + m_error.code= 4000; + return -1; + } memcpy(otherName, &data[pos], n << 2); - objectName = BaseString(otherName); + if (!(objectName = BaseString(otherName))) + { + m_error.code= 4000; + return -1; + } delete [] otherName; } - element.database = new char[databaseName.length() + 1]; + if (!(element.database = new char[databaseName.length() + 1]) || + !(element.schema = new char[schemaName.length() + 1]) || + !(element.name = new char[objectName.length() + 1])) + { + m_error.code= 4000; + return -1; + } strcpy(element.database, databaseName.c_str()); - element.schema = new char[schemaName.length() + 1]; strcpy(element.schema, schemaName.c_str()); - element.name = new char[objectName.length() + 1]; strcpy(element.name, objectName.c_str()); pos += n; count++; @@ -2427,7 +2578,10 @@ NdbDictInterface::execLIST_TABLES_CONF(NdbApiSignal* signal, { const unsigned off = ListTablesConf::HeaderLength; const unsigned len = (signal->getLength() - off); - m_buffer.append(signal->getDataPtr() + off, len << 2); + if (m_buffer.append(signal->getDataPtr() + off, len << 2)) + { + m_error.code= 4000; + } if (signal->getLength() < ListTablesConf::SignalLength) { // last signal has less than full length m_waiter.signal(NO_WAIT); diff --git a/ndb/src/ndbapi/NdbDictionaryImpl.hpp b/ndb/src/ndbapi/NdbDictionaryImpl.hpp index 6d58a703a3c..819de921235 100644 --- a/ndb/src/ndbapi/NdbDictionaryImpl.hpp +++ b/ndb/src/ndbapi/NdbDictionaryImpl.hpp @@ -103,7 +103,7 @@ public: ~NdbTableImpl(); void init(); - void setName(const char * name); + int setName(const char * name); const char * getName() const; Uint32 m_changeMask; @@ -120,7 +120,7 @@ public: Uint32 m_columnHashMask; Vector m_columnHash; Vector m_columns; - void buildColumnHash(); + int buildColumnHash(); /** * Fragment info @@ -166,7 +166,7 @@ public: * Equality/assign */ bool equal(const NdbTableImpl&) const; - void assign(const NdbTableImpl&); + int assign(const NdbTableImpl&); static NdbTableImpl & getImpl(NdbDictionary::Table & t); static NdbTableImpl & getImpl(const NdbDictionary::Table & t); @@ -185,9 +185,9 @@ public: ~NdbIndexImpl(); void init(); - void setName(const char * name); + int setName(const char * name); const char * getName() const; - void setTable(const char * table); + int setTable(const char * table); const char * getTable() const; const NdbTableImpl * getIndexTable() const; diff --git a/ndb/src/ndbapi/NdbImpl.hpp b/ndb/src/ndbapi/NdbImpl.hpp index 90b81dabff6..ec386074692 100644 --- a/ndb/src/ndbapi/NdbImpl.hpp +++ b/ndb/src/ndbapi/NdbImpl.hpp @@ -37,7 +37,7 @@ struct Ndb_free_list_t Ndb_free_list_t(); ~Ndb_free_list_t(); - void fill(Ndb*, Uint32 cnt); + int fill(Ndb*, Uint32 cnt); T* seize(Ndb*); void release(T*); void clear(); @@ -79,10 +79,14 @@ public: BaseString m_prefix; // Buffer for preformatted internal name // - void update_prefix() + int update_prefix() { - m_prefix.assfmt("%s%c%s%c", m_dbname.c_str(), table_name_separator, - m_schemaname.c_str(), table_name_separator); + if (!m_prefix.assfmt("%s%c%s%c", m_dbname.c_str(), table_name_separator, + m_schemaname.c_str(), table_name_separator)) + { + return -1; + } + return 0; } /** @@ -194,7 +198,7 @@ Ndb_free_list_t::~Ndb_free_list_t() template inline -void +int Ndb_free_list_t::fill(Ndb* ndb, Uint32 cnt) { if (m_free_list == 0) @@ -202,18 +206,28 @@ Ndb_free_list_t::fill(Ndb* ndb, Uint32 cnt) m_free_cnt++; m_alloc_cnt++; m_free_list = new T(ndb); + if (m_free_list == 0) + { + ndb->theError.code = 4000; + assert(false); + return -1; + } } while(m_alloc_cnt < cnt) { T* obj= new T(ndb); if(obj == 0) - return; - + { + ndb->theError.code = 4000; + assert(false); + return -1; + } obj->next(m_free_list); m_free_cnt++; m_alloc_cnt++; m_free_list = obj; } + return 0; } template @@ -234,7 +248,11 @@ Ndb_free_list_t::seize(Ndb* ndb) { m_alloc_cnt++; } - + else + { + ndb->theError.code = 4000; + assert(false); + } return tmp; } diff --git a/ndb/src/ndbapi/NdbOperation.cpp b/ndb/src/ndbapi/NdbOperation.cpp index 3ab1b56a717..51b6a3f6dab 100644 --- a/ndb/src/ndbapi/NdbOperation.cpp +++ b/ndb/src/ndbapi/NdbOperation.cpp @@ -176,7 +176,11 @@ NdbOperation::init(const NdbTableImpl* tab, NdbTransaction* myConnection){ tcKeyReq->scanInfo = 0; theKEYINFOptr = &tcKeyReq->keyInfo[0]; theATTRINFOptr = &tcKeyReq->attrInfo[0]; - theReceiver.init(NdbReceiver::NDB_OPERATION, this); + if (theReceiver.init(NdbReceiver::NDB_OPERATION, this)) + { + // theReceiver sets the error code of its owner + return -1; + } return 0; } diff --git a/ndb/src/ndbapi/NdbRecAttr.cpp b/ndb/src/ndbapi/NdbRecAttr.cpp index 90808a706d4..996c0256baa 100644 --- a/ndb/src/ndbapi/NdbRecAttr.cpp +++ b/ndb/src/ndbapi/NdbRecAttr.cpp @@ -83,6 +83,7 @@ NdbRecAttr::setup(const NdbColumnImpl* anAttrInfo, char* aValue) theRef = tRef; return 0; } + errno = ENOMEM; return -1; } @@ -102,7 +103,11 @@ NdbRecAttr::copyout() NdbRecAttr * NdbRecAttr::clone() const { NdbRecAttr * ret = new NdbRecAttr(0); - + if (ret == NULL) + { + errno = ENOMEM; + return NULL; + } ret->theAttrId = theAttrId; ret->theNULLind = theNULLind; ret->theAttrSize = theAttrSize; @@ -116,6 +121,12 @@ NdbRecAttr::clone() const { ret->theValue = 0; } else { ret->theStorageX = new Uint64[((n + 7) >> 3)]; + if (ret->theStorageX == NULL) + { + delete ret; + errno = ENOMEM; + return NULL; + } ret->theRef = (char*)ret->theStorageX; ret->theValue = 0; } @@ -508,3 +519,15 @@ NdbRecAttr::double_value() const memcpy(&val,theRef,sizeof(val)); return val; } + +Int32 +NdbRecAttr::medium_value() const +{ + return sint3korr((unsigned char *)theRef); +} + +Uint32 +NdbRecAttr::u_medium_value() const +{ + return uint3korr((unsigned char*)theRef); +} diff --git a/ndb/src/ndbapi/NdbReceiver.cpp b/ndb/src/ndbapi/NdbReceiver.cpp index 9322f88a351..46ca59f2f42 100644 --- a/ndb/src/ndbapi/NdbReceiver.cpp +++ b/ndb/src/ndbapi/NdbReceiver.cpp @@ -32,7 +32,7 @@ NdbReceiver::NdbReceiver(Ndb *aNdb) : { theCurrentRecAttr = theFirstRecAttr = 0; m_defined_rows = 0; - m_rows = new NdbRecAttr*[0]; + m_rows = NULL; } NdbReceiver::~NdbReceiver() @@ -45,19 +45,26 @@ NdbReceiver::~NdbReceiver() DBUG_VOID_RETURN; } -void +int NdbReceiver::init(ReceiverType type, void* owner) { theMagicNumber = 0x11223344; m_type = type; m_owner = owner; - if (m_id == NdbObjectIdMap::InvalidId) { - if (m_ndb) - m_id = m_ndb->theImpl->theNdbObjectIdMap.map(this); - } - theFirstRecAttr = NULL; theCurrentRecAttr = NULL; + if (m_id == NdbObjectIdMap::InvalidId) { + if (m_ndb) + { + m_id = m_ndb->theImpl->theNdbObjectIdMap.map(this); + if (m_id == NdbObjectIdMap::InvalidId) + { + setErrorCode(4000); + return -1; + } + } + } + return 0; } void @@ -146,7 +153,7 @@ NdbReceiver::calculate_batch_size(Uint32 key_size, return; } -void +int NdbReceiver::do_get_value(NdbReceiver * org, Uint32 rows, Uint32 key_size, @@ -154,7 +161,11 @@ NdbReceiver::do_get_value(NdbReceiver * org, if(rows > m_defined_rows){ delete[] m_rows; m_defined_rows = rows; - m_rows = new NdbRecAttr*[rows + 1]; + if ((m_rows = new NdbRecAttr*[rows + 1]) == NULL) + { + setErrorCode(4000); + return -1; + } } m_rows[rows] = 0; @@ -174,7 +185,7 @@ NdbReceiver::do_get_value(NdbReceiver * org, // Put key-recAttr fir on each row if(key_size && !getValue(&key, (char*)0)){ abort(); - return ; // -1 + return -1; } if(range_no && @@ -193,7 +204,7 @@ NdbReceiver::do_get_value(NdbReceiver * org, if(tRecAttr){ abort(); - return ;// -1; + return -1; } // Store first recAttr for each row in m_rows[i] @@ -205,7 +216,7 @@ NdbReceiver::do_get_value(NdbReceiver * org, } prepareSend(); - return; + return 0; } NdbRecAttr* diff --git a/ndb/src/ndbapi/NdbScanFilter.cpp b/ndb/src/ndbapi/NdbScanFilter.cpp index eb0ef4ba391..fb47772fdea 100644 --- a/ndb/src/ndbapi/NdbScanFilter.cpp +++ b/ndb/src/ndbapi/NdbScanFilter.cpp @@ -78,7 +78,11 @@ NdbScanFilter::~NdbScanFilter(){ int NdbScanFilter::begin(Group group){ - m_impl.m_stack2.push_back(m_impl.m_negative); + if (m_impl.m_stack2.push_back(m_impl.m_negative)) + { + m_impl.m_operation->setErrorCodeAbort(4000); + return -1; + } switch(group){ case NdbScanFilter::AND: INT_DEBUG(("Begin(AND)")); @@ -127,7 +131,11 @@ NdbScanFilter::begin(Group group){ } NdbScanFilterImpl::State tmp = m_impl.m_current; - m_impl.m_stack.push_back(m_impl.m_current); + if (m_impl.m_stack.push_back(m_impl.m_current)) + { + m_impl.m_operation->setErrorCodeAbort(4000); + return -1; + } m_impl.m_current.m_group = group; m_impl.m_current.m_ownLabel = m_impl.m_label++; m_impl.m_current.m_popCount = 0; diff --git a/ndb/src/ndbapi/NdbScanOperation.cpp b/ndb/src/ndbapi/NdbScanOperation.cpp index 8433b70f0b2..91c788b0088 100644 --- a/ndb/src/ndbapi/NdbScanOperation.cpp +++ b/ndb/src/ndbapi/NdbScanOperation.cpp @@ -797,9 +797,12 @@ int NdbScanOperation::prepareSendScan(Uint32 aTC_ConnectPtr, req->requestInfo = reqInfo; for(Uint32 i = 0; ido_get_value(&theReceiver, batch_size, - key_size, - m_read_range_no); + if (m_receivers[i]->do_get_value(&theReceiver, batch_size, + key_size, + m_read_range_no)) + { + return -1; + } } return 0; } diff --git a/ndb/src/ndbapi/NdbTransaction.cpp b/ndb/src/ndbapi/NdbTransaction.cpp index 2fe43b8cc21..258330b3967 100644 --- a/ndb/src/ndbapi/NdbTransaction.cpp +++ b/ndb/src/ndbapi/NdbTransaction.cpp @@ -81,6 +81,7 @@ NdbTransaction::NdbTransaction( Ndb* aNdb ) : { theListState = NotInList; theError.code = 0; + //theId = NdbObjectIdMap::InvalidId; theId = theNdb->theImpl->theNdbObjectIdMap.map(this); #define CHECK_SZ(mask, sz) assert((sizeof(mask)/sizeof(mask[0])) == sz) @@ -106,7 +107,7 @@ void init(); Remark: Initialise connection object for new transaction. *****************************************************************************/ -void +int NdbTransaction::init() { theListState = NotInList; @@ -147,6 +148,17 @@ NdbTransaction::init() // theBlobFlag = false; thePendingBlobOps = 0; + if (theId == NdbObjectIdMap::InvalidId) + { + theId = theNdb->theImpl->theNdbObjectIdMap.map(this); + if (theId == NdbObjectIdMap::InvalidId) + { + theError.code = 4000; + return -1; + } + } + return 0; + }//NdbTransaction::init() /***************************************************************************** diff --git a/ndb/src/ndbapi/Ndbif.cpp b/ndb/src/ndbapi/Ndbif.cpp index 75ec5df60cb..d404436be59 100644 --- a/ndb/src/ndbapi/Ndbif.cpp +++ b/ndb/src/ndbapi/Ndbif.cpp @@ -816,8 +816,9 @@ Ndb::handleReceivedSignal(NdbApiSignal* aSignal, LinearSectionPtr ptr[3]) InvalidSignal: #ifdef VM_TRACE ndbout_c("Ndbif: Error Ndb::handleReceivedSignal " - "(GSN=%d, theImpl->theWaiter.m_state=%d)" + "(tFirstDataPtr=%p, GSN=%d, theImpl->theWaiter.m_state=%d)" " sender = (Block: %d Node: %d)", + tFirstDataPtr, tSignalNumber, tWaitState, refToBlock(aSignal->theSendersBlockRef), diff --git a/ndb/src/ndbapi/Ndblist.cpp b/ndb/src/ndbapi/Ndblist.cpp index 812410e283f..443f9bb42fc 100644 --- a/ndb/src/ndbapi/Ndblist.cpp +++ b/ndb/src/ndbapi/Ndblist.cpp @@ -74,7 +74,10 @@ Ndb::checkFailedNode() int Ndb::createConIdleList(int aNrOfCon) { - theImpl->theConIdleList.fill(this, aNrOfCon); + if (theImpl->theConIdleList.fill(this, aNrOfCon)) + { + return -1; + } return aNrOfCon; } @@ -90,7 +93,10 @@ Ndb::createConIdleList(int aNrOfCon) int Ndb::createOpIdleList(int aNrOfOp) { - theImpl->theOpIdleList.fill(this, aNrOfOp); + if (theImpl->theOpIdleList.fill(this, aNrOfOp)) + { + return -1; + } return aNrOfOp; } diff --git a/ndb/src/ndbapi/ObjectMap.cpp b/ndb/src/ndbapi/ObjectMap.cpp new file mode 100644 index 00000000000..c87911a10d4 --- /dev/null +++ b/ndb/src/ndbapi/ObjectMap.cpp @@ -0,0 +1,62 @@ +/* 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; version 2 of the License. + + 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 "ObjectMap.hpp" + +NdbObjectIdMap::NdbObjectIdMap(NdbMutex* mutex, Uint32 sz, Uint32 eSz) +{ + m_size = 0; + m_firstFree = InvalidId; + m_map = 0; + m_mutex = mutex; + m_expandSize = eSz; + expand(sz); +#ifdef DEBUG_OBJECTMAP + ndbout_c("NdbObjectIdMap:::NdbObjectIdMap(%u)", sz); +#endif +} + +NdbObjectIdMap::~NdbObjectIdMap() +{ + free(m_map); +} + +int NdbObjectIdMap::expand(Uint32 incSize) +{ + NdbMutex_Lock(m_mutex); + Uint32 newSize = m_size + incSize; + MapEntry * tmp = (MapEntry*)realloc(m_map, newSize * sizeof(MapEntry)); + + if (likely(tmp != 0)) + { + m_map = tmp; + + for(Uint32 i = m_size; i < newSize; i++){ + m_map[i].m_next = i + 1; + } + m_firstFree = m_size; + m_map[newSize-1].m_next = InvalidId; + m_size = newSize; + } + else + { + NdbMutex_Unlock(m_mutex); + g_eventLogger.error("NdbObjectIdMap::expand: realloc(%u*%u) failed", + newSize, sizeof(MapEntry)); + return -1; + } + NdbMutex_Unlock(m_mutex); + return 0; +} diff --git a/ndb/src/ndbapi/ObjectMap.hpp b/ndb/src/ndbapi/ObjectMap.hpp index 0e0c9668164..6a8dbcbeef5 100644 --- a/ndb/src/ndbapi/ObjectMap.hpp +++ b/ndb/src/ndbapi/ObjectMap.hpp @@ -20,6 +20,9 @@ //#include #include +#include +extern EventLogger g_eventLogger; + //#define DEBUG_OBJECTMAP /** @@ -49,24 +52,6 @@ private: int expand(Uint32 newSize); }; -inline -NdbObjectIdMap::NdbObjectIdMap(NdbMutex* mutex, Uint32 sz, Uint32 eSz) { - m_size = 0; - m_firstFree = InvalidId; - m_map = 0; - m_mutex = mutex; - m_expandSize = eSz; - expand(sz); -#ifdef DEBUG_OBJECTMAP - ndbout_c("NdbObjectIdMap:::NdbObjectIdMap(%u)", sz); -#endif -} - -inline -NdbObjectIdMap::~NdbObjectIdMap(){ - free(m_map); -} - inline Uint32 NdbObjectIdMap::map(void * object){ @@ -102,7 +87,8 @@ NdbObjectIdMap::unmap(Uint32 id, void *object){ m_map[i].m_next = m_firstFree; m_firstFree = i; } else { - ndbout_c("Error: NdbObjectIdMap::::unmap(%u, 0x%x) obj=0x%x", id, object, obj); + g_eventLogger.error("NdbObjectIdMap::unmap(%u, 0x%x) obj=0x%x", + id, object, obj); return 0; } @@ -128,31 +114,4 @@ NdbObjectIdMap::getObject(Uint32 id){ } return 0; } - -inline int -NdbObjectIdMap::expand(Uint32 incSize){ - NdbMutex_Lock(m_mutex); - Uint32 newSize = m_size + incSize; - MapEntry * tmp = (MapEntry*)realloc(m_map, newSize * sizeof(MapEntry)); - - if (likely(tmp != 0)) - { - m_map = tmp; - - for(Uint32 i = m_size; i= 0 && m_impl.m_all_nodes[i].group > m_impl.m_all_nodes[i+1].group; @@ -449,7 +452,7 @@ Ndb_cluster_connection_impl::init_nodes_vector(Uint32 nodeid, do_test(); #endif - DBUG_VOID_RETURN; + DBUG_RETURN(0); } void @@ -532,7 +535,11 @@ int Ndb_cluster_connection::connect(int no_retries, int retry_delay_in_seconds, break; m_impl.m_transporter_facade->start_instance(nodeId, props); - m_impl.init_nodes_vector(nodeId, *props); + if (m_impl.init_nodes_vector(nodeId, *props)) + { + ndbout_c("Ndb_cluster_connection::connect: malloc failure"); + DBUG_RETURN(-1); + } for(unsigned i=0; iget_registry()->m_transporter_interface.size(); diff --git a/ndb/src/ndbapi/ndb_cluster_connection_impl.hpp b/ndb/src/ndbapi/ndb_cluster_connection_impl.hpp index 5bb5f0a0fca..d3ff7610e18 100644 --- a/ndb/src/ndbapi/ndb_cluster_connection_impl.hpp +++ b/ndb/src/ndbapi/ndb_cluster_connection_impl.hpp @@ -68,7 +68,7 @@ private: }; Vector m_all_nodes; - void init_nodes_vector(Uint32 nodeid, const ndb_mgm_configuration &config); + int init_nodes_vector(Uint32 nodeid, const ndb_mgm_configuration &config); void connect_thread(); void set_name(const char *name); diff --git a/ndb/tools/restore/Restore.hpp b/ndb/tools/restore/Restore.hpp index 66e00d88dfe..c1545159ce4 100644 --- a/ndb/tools/restore/Restore.hpp +++ b/ndb/tools/restore/Restore.hpp @@ -219,6 +219,9 @@ public: memcpy(&val.u32,data,4); v= val.u32; break; + case 24: + v= uint3korr((unsigned char*)data); + break; case 16: memcpy(&val.u16,data,2); v= val.u16; diff --git a/ndb/tools/restore/consumer_restore.cpp b/ndb/tools/restore/consumer_restore.cpp index c955570eaa3..811868f3e77 100644 --- a/ndb/tools/restore/consumer_restore.cpp +++ b/ndb/tools/restore/consumer_restore.cpp @@ -205,7 +205,7 @@ BackupRestore::table(const TableS & table){ BaseString tmp(name); Vector split; if(tmp.split(split, "/") != 3){ - err << "Invalid table name format " << name << endl; + err << "Invalid table name format `" << name << "`" << endl; return false; } @@ -230,16 +230,17 @@ BackupRestore::table(const TableS & table){ if (dict->createTable(copy) == -1) { - err << "Create table " << table.getTableName() << " failed: " + err << "Create table `" << table.getTableName() << "` failed: " << dict->getNdbError() << endl; return false; } - info << "Successfully restored table " << table.getTableName()<< endl ; + info << "Successfully restored table `" + << table.getTableName() << "`" << endl; } const NdbDictionary::Table* tab = dict->getTable(split[2].c_str()); if(tab == 0){ - err << "Unable to find table: " << split[2].c_str() << endl; + err << "Unable to find table: `" << split[2].c_str() << "`" << endl; return false; } const NdbDictionary::Table* null = 0; @@ -257,12 +258,15 @@ BackupRestore::endOfTables(){ for(size_t i = 0; i split; - if(tmp.split(split, "/") != 3){ - err << "Invalid table name format " << indtab.m_primaryTable.c_str() - << endl; - return false; + { + BaseString tmp(indtab.m_primaryTable.c_str()); + if (tmp.split(split, "/") != 3) + { + err << "Invalid table name format `" << indtab.m_primaryTable.c_str() + << "`" << endl; + return false; + } } m_ndb->setDatabaseName(split[0].c_str()); @@ -270,39 +274,41 @@ BackupRestore::endOfTables(){ const NdbDictionary::Table * prim = dict->getTable(split[2].c_str()); if(prim == 0){ - err << "Unable to find base table \"" << split[2].c_str() - << "\" for index " - << indtab.getName() << endl; + err << "Unable to find base table `" << split[2].c_str() + << "` for index `" + << indtab.getName() << "`" << endl; return false; } NdbTableImpl& base = NdbTableImpl::getImpl(*prim); NdbIndexImpl* idx; - int id; - char idxName[255], buf[255]; - if(sscanf(indtab.getName(), "%[^/]/%[^/]/%d/%s", - buf, buf, &id, idxName) != 4){ - err << "Invalid index name format " << indtab.getName() << endl; - return false; + Vector split_idx; + { + BaseString tmp(indtab.getName()); + if (tmp.split(split_idx, "/") != 4) + { + err << "Invalid index name format `" << indtab.getName() << "`" << endl; + return false; + } } if(NdbDictInterface::create_index_obj_from_table(&idx, &indtab, &base)) { - err << "Failed to create index " << idxName - << " on " << split[2].c_str() << endl; + err << "Failed to create index `" << split_idx[3] + << "` on " << split[2].c_str() << endl; return false; } - idx->setName(idxName); + idx->setName(split_idx[3].c_str()); if(dict->createIndex(* idx) != 0) { delete idx; - err << "Failed to create index " << idxName - << " on " << split[2].c_str() << endl + err << "Failed to create index `" << split_idx[3].c_str() + << "` on `" << split[2].c_str() << "`" << endl << dict->getNdbError() << endl; return false; } delete idx; - info << "Successfully created index " << idxName - << " on " << split[2].c_str() << endl; + info << "Successfully created index `" << split_idx[3].c_str() + << "` on `" << split[2].c_str() << "`" << endl; } return true; } @@ -382,7 +388,7 @@ void BackupRestore::tuple_a(restore_callback_t *cb) Uint32 length = (size * arraySize) / 8; if (j == 0 && tup.getTable()->have_auto_inc(i)) - tup.getTable()->update_max_auto_val(dataPtr,size); + tup.getTable()->update_max_auto_val(dataPtr,size*arraySize); if (attr_desc->m_column->getPrimaryKey()) { @@ -596,7 +602,7 @@ BackupRestore::logEntry(const LogEntry & tup) const char * dataPtr = attr->Data.string_value; if (tup.m_table->have_auto_inc(attr->Desc->attrId)) - tup.m_table->update_max_auto_val(dataPtr,size); + tup.m_table->update_max_auto_val(dataPtr,size*arraySize); const Uint32 length = (size / 8) * arraySize; if (attr->Desc->m_column->getPrimaryKey()) diff --git a/ndb/tools/restore/restore_main.cpp b/ndb/tools/restore/restore_main.cpp index 52a913d73b4..9ec59b9b4a6 100644 --- a/ndb/tools/restore/restore_main.cpp +++ b/ndb/tools/restore/restore_main.cpp @@ -559,8 +559,8 @@ main(int argc, char** argv) for(Uint32 j= 0; j < g_consumers.size(); j++) if (!g_consumers[j]->table(* table)) { - err << "Restore: Failed to restore table: "; - err << table->getTableName() << " ... Exiting " << endl; + err << "Restore: Failed to restore table: `"; + err << table->getTableName() << "` ... Exiting " << endl; exitHandler(NDBT_FAILED); } } diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 33744b49cef..8bca5ea7c5c 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -203,6 +203,7 @@ static const err_code_mapping err_map[]= { 284, HA_ERR_TABLE_DEF_CHANGED, 0 }, + {4000, HA_ERR_OUT_OF_MEM, 1 }, {4009, HA_ERR_NO_CONNECTION, 1 }, { 0, 1, 0 }, @@ -372,7 +373,10 @@ int ha_ndbcluster::records_update() { Ndb *ndb= get_ndb(); struct Ndb_statistics stat; - ndb->setDatabaseName(m_dbname); + if (ndb->setDatabaseName(m_dbname)) + { + return my_errno= HA_ERR_OUT_OF_MEM; + } result= ndb_get_table_statistics(this, true, ndb, m_tabname, &stat); if (result == 0) { @@ -841,7 +845,11 @@ int ha_ndbcluster::get_ndb_blobs_value(NdbBlob *last_ndb_blob, DBUG_PRINT("value", ("allocate blobs buffer size %u", offset)); m_blobs_buffer= my_malloc(offset, MYF(MY_WME)); if (m_blobs_buffer == NULL) + { + sql_print_error("ha_ndbcluster::get_ndb_blobs_value: " + "my_malloc(%u) failed", offset); DBUG_RETURN(-1); + } m_blobs_buffer_size= offset; } } @@ -1026,6 +1034,12 @@ static int fix_unique_index_attr_order(NDB_INDEX_DATA &data, if (data.unique_index_attrid_map) my_free((char*)data.unique_index_attrid_map, MYF(0)); data.unique_index_attrid_map= (unsigned char*)my_malloc(sz,MYF(MY_WME)); + if (data.unique_index_attrid_map == 0) + { + sql_print_error("fix_unique_index_attr_order: my_malloc(%u) failure", + (unsigned int)sz); + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } KEY_PART_INFO* key_part= key_info->key_part; KEY_PART_INFO* end= key_part+key_info->key_parts; @@ -1134,14 +1148,16 @@ int ha_ndbcluster::build_index_list(Ndb *ndb, TABLE *tab, enum ILBP phase) { DBUG_PRINT("info", ("Get handle to index %s", index_name)); const NDBINDEX *index= dict->getIndex(index_name, m_tabname); - if (!index) DBUG_RETURN(1); + if (!index) + ERR_RETURN(dict->getNdbError()); m_index[i].index= (void *) index; } if (idx_type == UNIQUE_ORDERED_INDEX || idx_type == UNIQUE_INDEX) { DBUG_PRINT("info", ("Get handle to unique_index %s", unique_index_name)); const NDBINDEX *index= dict->getIndex(unique_index_name, m_tabname); - if (!index) DBUG_RETURN(1); + if (!index) + ERR_RETURN(dict->getNdbError()); m_index[i].unique_index= (void *) index; error= fix_unique_index_attr_order(m_index[i], index, key_info); } @@ -3228,7 +3244,10 @@ int ha_ndbcluster::info(uint flag) DBUG_RETURN(my_errno); Ndb *ndb= get_ndb(); struct Ndb_statistics stat; - ndb->setDatabaseName(m_dbname); + if (ndb->setDatabaseName(m_dbname)) + { + DBUG_RETURN(my_errno= HA_ERR_OUT_OF_MEM); + } if (current_thd->variables.ndb_use_exact_count && (result= ndb_get_table_statistics(this, true, ndb, m_tabname, &stat)) == 0) @@ -4037,7 +4056,10 @@ static int create_ndb_column(NDBCOL &col, HA_CREATE_INFO *info) { // Set name - col.setName(field->field_name); + if (col.setName(field->field_name)) + { + return (my_errno= errno); + } // Get char set CHARSET_INFO *cs= field->charset(); // Set type and sizes @@ -4409,7 +4431,10 @@ int ha_ndbcluster::create(const char *name, } DBUG_PRINT("table", ("name: %s", m_tabname)); - tab.setName(m_tabname); + if (tab.setName(m_tabname)) + { + DBUG_RETURN(my_errno= errno); + } tab.setLogging(!(create_info->options & HA_LEX_CREATE_TMP_TABLE)); // Save frm data for this table @@ -4434,7 +4459,10 @@ int ha_ndbcluster::create(const char *name, field->pack_length())); if ((my_errno= create_ndb_column(col, field, create_info))) DBUG_RETURN(my_errno); - tab.addColumn(col); + if (tab.addColumn(col)) + { + DBUG_RETURN(my_errno= errno); + } if (col.getPrimaryKey()) pk_length += (field->pack_length() + 3) / 4; } @@ -4443,13 +4471,19 @@ int ha_ndbcluster::create(const char *name, if (form->s->primary_key == MAX_KEY) { DBUG_PRINT("info", ("Generating shadow key")); - col.setName("$PK"); + if (col.setName("$PK")) + { + DBUG_RETURN(my_errno= errno); + } col.setType(NdbDictionary::Column::Bigunsigned); col.setLength(1); col.setNullable(FALSE); col.setPrimaryKey(TRUE); col.setAutoIncrement(TRUE); - tab.addColumn(col); + if (tab.addColumn(col)) + { + DBUG_RETURN(my_errno= errno); + } pk_length += 2; } @@ -4555,13 +4589,19 @@ int ha_ndbcluster::create_index(const char *name, // TODO Only temporary ordered indexes supported ndb_index.setLogging(FALSE); } - ndb_index.setTable(m_tabname); + if (ndb_index.setTable(m_tabname)) + { + DBUG_RETURN(my_errno= errno); + } for (; key_part != end; key_part++) { Field *field= key_part->field; DBUG_PRINT("info", ("attr: %s", field->field_name)); - ndb_index.addColumnName(field->field_name); + if (ndb_index.addColumnName(field->field_name)) + { + DBUG_RETURN(my_errno= errno); + } } if (dict->createIndex(ndb_index)) @@ -4616,7 +4656,10 @@ int ha_ndbcluster::rename_table(const char *from, const char *to) m_table= (void *)orig_tab; // Change current database to that of target table set_dbname(to); - ndb->setDatabaseName(m_dbname); + if (ndb->setDatabaseName(m_dbname)) + { + ERR_RETURN(ndb->getNdbError()); + } if (!(result= alter_table_name(new_tabname))) { // Rename .ndb file @@ -4635,10 +4678,16 @@ int ha_ndbcluster::rename_table(const char *from, const char *to) for (unsigned i = 0; i < index_list.count; i++) { NDBDICT::List::Element& index_el = index_list.elements[i]; set_dbname(from); - ndb->setDatabaseName(m_dbname); + if (ndb->setDatabaseName(m_dbname)) + { + ERR_RETURN(ndb->getNdbError()); + } const NDBINDEX * index= dict->getIndex(index_el.name, *new_tab); set_dbname(to); - ndb->setDatabaseName(m_dbname); + if (ndb->setDatabaseName(m_dbname)) + { + ERR_RETURN(ndb->getNdbError()); + } DBUG_PRINT("info", ("Creating index %s/%s", m_dbname, index->getName())); dict->createIndex(*index); @@ -4646,7 +4695,10 @@ int ha_ndbcluster::rename_table(const char *from, const char *to) m_dbname, index->getName())); set_dbname(from); - ndb->setDatabaseName(m_dbname); + if (ndb->setDatabaseName(m_dbname)) + { + ERR_RETURN(ndb->getNdbError()); + } dict->dropIndex(*index); } } @@ -4667,7 +4719,10 @@ int ha_ndbcluster::alter_table_name(const char *to) DBUG_ENTER("alter_table_name_table"); NdbDictionary::Table new_tab= *orig_tab; - new_tab.setName(to); + if (new_tab.setName(to)) + { + DBUG_RETURN(my_errno= errno); + } if (dict->alterTable(new_tab) != 0) ERR_RETURN(dict->getNdbError()); @@ -4913,7 +4968,10 @@ int ha_ndbcluster::open(const char *name, int mode, uint test_if_locked) if (!res) { Ndb *ndb= get_ndb(); - ndb->setDatabaseName(m_dbname); + if (ndb->setDatabaseName(m_dbname)) + { + ERR_RETURN(ndb->getNdbError()); + } struct Ndb_statistics stat; res= ndb_get_table_statistics(NULL, false, ndb, m_tabname, &stat); records= stat.row_count; @@ -4945,6 +5003,11 @@ Thd_ndb* ha_ndbcluster::seize_thd_ndb() DBUG_ENTER("seize_thd_ndb"); thd_ndb= new Thd_ndb(); + if (thd_ndb == NULL) + { + my_errno= HA_ERR_OUT_OF_MEM; + return NULL; + } thd_ndb->ndb->getDictionary()->set_local_table_data_size( sizeof(Ndb_local_table_statistics) ); @@ -5000,7 +5063,10 @@ int ha_ndbcluster::check_ndb_connection(THD* thd) if (!(ndb= check_ndb_in_thd(thd))) DBUG_RETURN(HA_ERR_NO_CONNECTION); - ndb->setDatabaseName(m_dbname); + if (ndb->setDatabaseName(m_dbname)) + { + ERR_RETURN(ndb->getNdbError()); + } DBUG_RETURN(0); } @@ -5034,8 +5100,10 @@ int ndbcluster_discover(THD* thd, const char *db, const char *name, if (!(ndb= check_ndb_in_thd(thd))) DBUG_RETURN(HA_ERR_NO_CONNECTION); - ndb->setDatabaseName(db); - + if (ndb->setDatabaseName(db)) + { + ERR_RETURN(ndb->getNdbError()); + } NDBDICT* dict= ndb->getDictionary(); dict->set_local_table_data_size(sizeof(Ndb_local_table_statistics)); dict->invalidateTable(name); @@ -5081,8 +5149,10 @@ int ndbcluster_table_exists_in_engine(THD* thd, const char *db, const char *name if (!(ndb= check_ndb_in_thd(thd))) DBUG_RETURN(HA_ERR_NO_CONNECTION); - ndb->setDatabaseName(db); - + if (ndb->setDatabaseName(db)) + { + ERR_RETURN(ndb->getNdbError()); + } NDBDICT* dict= ndb->getDictionary(); dict->set_local_table_data_size(sizeof(Ndb_local_table_statistics)); dict->invalidateTable(name); @@ -5143,7 +5213,10 @@ int ndbcluster_drop_database(const char *path) drop_list.push_back(thd->strdup(t.name)); } // Drop any tables belonging to database - ndb->setDatabaseName(dbname); + if (ndb->setDatabaseName(dbname)) + { + ERR_RETURN(ndb->getNdbError()); + } List_iterator_fast it(drop_list); while ((tabname=it++)) { @@ -5372,6 +5445,7 @@ bool ndbcluster_init() { DBUG_PRINT("error",("Ndb_cluster_connection(%s)", opt_ndbcluster_connectstring)); + my_errno= HA_ERR_OUT_OF_MEM; goto ndbcluster_init_error; } { @@ -5386,6 +5460,7 @@ bool ndbcluster_init() if ( (g_ndb= new Ndb(g_ndb_cluster_connection, "sys")) == 0 ) { DBUG_PRINT("error", ("failed to create global ndb object")); + my_errno= HA_ERR_OUT_OF_MEM; goto ndbcluster_init_error; } g_ndb->getDictionary()->set_local_table_data_size(sizeof(Ndb_local_table_statistics)); @@ -5741,7 +5816,10 @@ uint ndb_get_commitcount(THD *thd, char *dbname, char *tabname, Ndb *ndb; if (!(ndb= check_ndb_in_thd(thd))) DBUG_RETURN(1); - ndb->setDatabaseName(dbname); + if (ndb->setDatabaseName(dbname)) + { + ERR_RETURN(ndb->getNdbError()); + } uint lock= share->commit_count_lock; pthread_mutex_unlock(&share->mutex); @@ -5954,6 +6032,8 @@ static NDB_SHARE* get_share(const char *table_name) { DBUG_PRINT("error", ("Failed to alloc share")); pthread_mutex_unlock(&ndbcluster_mutex); + sql_print_error("get_share: my_malloc(%u) failed", + (unsigned int)(sizeof(*share)+length+1)); return 0; } } @@ -6014,16 +6094,22 @@ static int packfrm(const void *data, uint len, error= 1; org_len= len; if (my_compress((byte*)data, &org_len, &comp_len)) + { + sql_print_error("packfrm: my_compress(org_len: %u)", + (unsigned int)org_len); goto err; - + } + DBUG_PRINT("info", ("org_len: %lu comp_len: %lu", org_len, comp_len)); DBUG_DUMP("compressed", (char*)data, org_len); error= 2; blob_len= sizeof(frm_blob_struct::frm_blob_header)+org_len; if (!(blob= (frm_blob_struct*) my_malloc(blob_len,MYF(MY_WME)))) + { + sql_print_error("packfrm: my_malloc(%u)", blob_len); goto err; - + } // Store compressed blob in machine independent format int4store((char*)(&blob->head.ver), 1); int4store((char*)(&blob->head.orglen), comp_len); @@ -6062,14 +6148,23 @@ static int unpackfrm(const void **unpack_data, uint *unpack_len, DBUG_DUMP("blob->data", (char*) blob->data, complen); if (ver != 1) + { + sql_print_error("unpackfrm: ver != 1"); DBUG_RETURN(1); + } if (!(data= my_malloc(max(orglen, complen), MYF(MY_WME)))) - DBUG_RETURN(2); + { + sql_print_error("unpackfrm: my_malloc(%u)", + (unsigned int)max(orglen, complen)); + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } memcpy(data, blob->data, complen); if (my_uncompress(data, &complen, &orglen)) { my_free((char*)data, MYF(0)); + sql_print_error("unpackfrm: my_uncompress(complen: %u, orglen: %u)", + (unsigned int)complen, (unsigned int)orglen); DBUG_RETURN(3); } @@ -6664,7 +6759,10 @@ ha_ndbcluster::update_table_comment( return((char*)comment); } - ndb->setDatabaseName(m_dbname); + if (ndb->setDatabaseName(m_dbname)) + { + return((char*)comment); + } NDBDICT* dict= ndb->getDictionary(); const NDBTAB* tab; if (!(tab= dict->getTable(m_tabname))) @@ -6677,6 +6775,8 @@ ha_ndbcluster::update_table_comment( const unsigned fmt_len_plus_extra= length + strlen(fmt); if ((str= my_malloc(fmt_len_plus_extra, MYF(0))) == NULL) { + sql_print_error("ha_ndbcluster::update_table_comment: " + "my_malloc(%u) failed", (unsigned int)fmt_len_plus_extra); return (char*)comment; } @@ -6699,9 +6799,19 @@ pthread_handler_t ndb_util_thread_func(void *arg __attribute__((unused))) DBUG_PRINT("enter", ("ndb_cache_check_time: %lu", ndb_cache_check_time)); thd= new THD; /* note that contructor of THD uses DBUG_ */ + if (thd == NULL) + { + my_errno= HA_ERR_OUT_OF_MEM; + DBUG_RETURN(NULL); + } THD_CHECK_SENTRY(thd); ndb= new Ndb(g_ndb_cluster_connection, ""); - + if (ndb == NULL) + { + thd->cleanup(); + delete thd; + DBUG_RETURN(NULL); + } pthread_detach_this_thread(); ndb_util_thread= pthread_self(); @@ -6790,14 +6900,15 @@ pthread_handler_t ndb_util_thread_func(void *arg __attribute__((unused))) share->table_name)); /* Contact NDB to get commit count for table */ - ndb->setDatabaseName(db); struct Ndb_statistics stat; - uint lock; pthread_mutex_lock(&share->mutex); lock= share->commit_count_lock; pthread_mutex_unlock(&share->mutex); - + if (ndb->setDatabaseName(db)) + { + goto loop_next; + } if (ndb_get_table_statistics(NULL, false, ndb, tabname, &stat) == 0) { #ifndef DBUG_OFF @@ -6816,7 +6927,7 @@ pthread_handler_t ndb_util_thread_func(void *arg __attribute__((unused))) share->table_name)); stat.commit_count= 0; } - + loop_next: pthread_mutex_lock(&share->mutex); if (share->commit_count_lock == lock) share->commit_count= stat.commit_count; @@ -6885,6 +6996,11 @@ ha_ndbcluster::cond_push(const COND *cond) { DBUG_ENTER("cond_push"); Ndb_cond_stack *ndb_cond = new Ndb_cond_stack(); + if (ndb_cond == NULL) + { + my_errno= HA_ERR_OUT_OF_MEM; + DBUG_RETURN(NULL); + } DBUG_EXECUTE("where",print_where((COND *)cond, m_tabname);); if (m_cond_stack) ndb_cond->next= m_cond_stack; diff --git a/sql/item.cc b/sql/item.cc index 8568a44c547..ed5bd67d096 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1610,7 +1610,7 @@ void Item_ident_for_show::make_field(Send_field *tmp_field) Item_field::Item_field(Field *f) :Item_ident(0, NullS, *f->table_name, f->field_name), item_equal(0), no_const_subst(0), - have_privileges(0), any_privileges(0), fixed_as_field(0) + have_privileges(0), any_privileges(0) { set_field(f); /* @@ -1624,7 +1624,7 @@ Item_field::Item_field(THD *thd, Name_resolution_context *context_arg, Field *f) :Item_ident(context_arg, f->table->s->db, *f->table_name, f->field_name), item_equal(0), no_const_subst(0), - have_privileges(0), any_privileges(0), fixed_as_field(0) + have_privileges(0), any_privileges(0) { /* We always need to provide Item_field with a fully qualified field @@ -1663,7 +1663,7 @@ Item_field::Item_field(Name_resolution_context *context_arg, const char *field_name_arg) :Item_ident(context_arg, db_arg,table_name_arg,field_name_arg), field(0), result_field(0), item_equal(0), no_const_subst(0), - have_privileges(0), any_privileges(0), fixed_as_field(0) + have_privileges(0), any_privileges(0) { SELECT_LEX *select= current_thd->lex->current_select; collation.set(DERIVATION_IMPLICIT); @@ -1679,8 +1679,7 @@ Item_field::Item_field(THD *thd, Item_field *item) item_equal(item->item_equal), no_const_subst(item->no_const_subst), have_privileges(item->have_privileges), - any_privileges(item->any_privileges), - fixed_as_field(item->fixed_as_field) + any_privileges(item->any_privileges) { collation.set(DERIVATION_IMPLICIT); } @@ -3447,6 +3446,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) Item **ref= (Item **) not_found_item; SELECT_LEX *current_sel= (SELECT_LEX *) thd->lex->current_select; Name_resolution_context *outer_context= 0; + SELECT_LEX *select= 0; /* Currently derived tables cannot be correlated */ if (current_sel->master_unit()->first_select()->linkage != DERIVED_TABLE_TYPE) @@ -3455,7 +3455,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) outer_context; outer_context= outer_context->outer_context) { - SELECT_LEX *select= outer_context->select_lex; + select= outer_context->select_lex; Item_subselect *prev_subselect_item= last_checked_context->select_lex->master_unit()->item; last_checked_context= outer_context; @@ -3498,45 +3498,28 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) } if (*from_field != view_ref_found) { - prev_subselect_item->used_tables_cache|= (*from_field)->table->map; prev_subselect_item->const_item_cache= 0; + set_field(*from_field); if (!last_checked_context->select_lex->having_fix_field && - !fixed_as_field) + select->group_list.elements) { Item_outer_ref *rf; - Query_arena *arena= 0, backup; /* - Each outer field is replaced for an Item_outer_ref object. - This is done in order to get correct results when the outer - select employs a temporary table. - The original fields are saved in the inner_fields_list of the - outer select. This list is created by the following reasons: - 1. We can't add field items to the outer select list directly - because the outer select hasn't been fully fixed yet. - 2. We need a location to refer to in the Item_ref object - so the inner_fields_list is used as such temporary - reference storage. - The new Item_outer_ref object replaces the original field and is - also saved in the inner_refs_list of the outer select. Here - it is only created. It can be fixed only after the original - field has been fixed and this is done in the fix_inner_refs() - function. + If an outer field is resolved in a grouping select then it + is replaced for an Item_outer_ref object. Otherwise an + Item_field object is used. + The new Item_outer_ref object is saved in the inner_refs_list of + the outer select. Here it is only created. It can be fixed only + after the original field has been fixed and this is done in the + fix_inner_refs() function. */ - set_field(*from_field); - arena= thd->activate_stmt_arena_if_needed(&backup); - rf= new Item_outer_ref(context, this); - if (!rf) - { - if (arena) - thd->restore_active_arena(arena, &backup); + ; + if (!(rf= new Item_outer_ref(context, this))) return -1; - } - *reference= rf; + thd->change_item_tree(reference, rf); select->inner_refs_list.push_back(rf); - if (arena) - thd->restore_active_arena(arena, &backup); - fixed_as_field= 1; + rf->in_sum_func= thd->lex->in_sum_func; } if (thd->lex->in_sum_func && thd->lex->in_sum_func->nest_level == @@ -3642,11 +3625,20 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) rf= (place == IN_HAVING ? new Item_ref(context, ref, (char*) table_name, (char*) field_name, alias_name_used) : + (!select->group_list.elements ? new Item_direct_ref(context, ref, (char*) table_name, - (char*) field_name, alias_name_used)); + (char*) field_name, alias_name_used) : + new Item_outer_ref(context, ref, (char*) table_name, + (char*) field_name, alias_name_used))); *ref= save; if (!rf) return -1; + + if (place != IN_HAVING && select->group_list.elements) + { + outer_context->select_lex->inner_refs_list.push_back((Item_outer_ref*)rf); + ((Item_outer_ref*)rf)->in_sum_func= thd->lex->in_sum_func; + } thd->change_item_tree(reference, rf); /* rf is Item_ref => never substitute other items (in this case) @@ -5550,16 +5542,19 @@ bool Item_direct_view_ref::fix_fields(THD *thd, Item **reference) bool Item_outer_ref::fix_fields(THD *thd, Item **reference) { - DBUG_ASSERT(*ref); - /* outer_field->check_cols() will be made in Item_direct_ref::fix_fields */ - outer_field->fixed_as_field= 1; - if (!outer_field->fixed && - (outer_field->fix_fields(thd, reference))) + bool err; + /* outer_ref->check_cols() will be made in Item_direct_ref::fix_fields */ + if ((*ref) && !(*ref)->fixed && ((*ref)->fix_fields(thd, reference))) return TRUE; - table_name= outer_field->table_name; - return Item_direct_ref::fix_fields(thd, reference); + err= Item_direct_ref::fix_fields(thd, reference); + if (!outer_ref) + outer_ref= *ref; + if ((*ref)->type() == Item::FIELD_ITEM) + table_name= ((Item_field*)outer_ref)->table_name; + return err; } + /* Compare two view column references for equality. diff --git a/sql/item.h b/sql/item.h index 2c4943bea6e..094c45642da 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1220,7 +1220,6 @@ public: uint have_privileges; /* field need any privileges (for VIEW creation) */ bool any_privileges; - bool fixed_as_field; Item_field(Name_resolution_context *context_arg, const char *db_arg,const char *table_name_arg, const char *field_name_arg); @@ -1978,30 +1977,49 @@ public: }; +/* + Class for outer fields. + An object of this class is created when the select where the outer field was + resolved is a grouping one. After it has been fixed the ref field will point + to either an Item_ref or an Item_direct_ref object which will be used to + access the field. + See also comments for the fix_inner_refs() and the + Item_field::fix_outer_field() functions. +*/ + +class Item_sum; class Item_outer_ref :public Item_direct_ref { public: - Item_field *outer_field; + Item *outer_ref; + /* The aggregate function under which this outer ref is used, if any. */ + Item_sum *in_sum_func; + /* + TRUE <=> that the outer_ref is already present in the select list + of the outer select. + */ + bool found_in_select_list; Item_outer_ref(Name_resolution_context *context_arg, Item_field *outer_field_arg) :Item_direct_ref(context_arg, 0, outer_field_arg->table_name, - outer_field_arg->field_name), - outer_field(outer_field_arg) + outer_field_arg->field_name), + outer_ref(outer_field_arg), in_sum_func(0), + found_in_select_list(0) { - ref= (Item**)&outer_field; + ref= &outer_ref; set_properties(); fixed= 0; } - void cleanup() - { - ref= (Item**)&outer_field; - fixed= 0; - Item_direct_ref::cleanup(); - outer_field->cleanup(); - } + Item_outer_ref(Name_resolution_context *context_arg, Item **item, + const char *table_name_arg, const char *field_name_arg, + bool alias_name_used_arg) + :Item_direct_ref(context_arg, item, table_name_arg, field_name_arg, + alias_name_used_arg), + outer_ref(0), in_sum_func(0), found_in_select_list(1) + {} void save_in_result_field(bool no_conversions) { - outer_field->save_org_in_field(result_field); + outer_ref->save_org_in_field(result_field); } bool fix_fields(THD *, Item **); table_map used_tables() const diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 3bb537c2fd5..1c0ece8877b 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -68,6 +68,42 @@ static void agg_result_type(Item_result *type, Item **items, uint nitems) } +/* + Compare row signature of two expressions + + SYNOPSIS: + cmp_row_type() + item1 the first expression + item2 the second expression + + DESCRIPTION + The function checks that two expressions have compatible row signatures + i.e. that the number of columns they return are the same and that if they + are both row expressions then each component from the first expression has + a row signature compatible with the signature of the corresponding component + of the second expression. + + RETURN VALUES + 1 type incompatibility has been detected + 0 otherwise +*/ + +static int cmp_row_type(Item* item1, Item* item2) +{ + uint n= item1->cols(); + if (item2->check_cols(n)) + return 1; + for (uint i=0; ielement_index(i)->check_cols(item1->element_index(i)->cols()) || + (item1->element_index(i)->result_type() == ROW_RESULT && + cmp_row_type(item1->element_index(i), item2->element_index(i)))) + return 1; + } + return 0; +} + + /* Aggregates result types from the array of items. @@ -82,14 +118,32 @@ static void agg_result_type(Item_result *type, Item **items, uint nitems) This function aggregates result types from the array of items. Found type supposed to be used later for comparison of values of these items. Aggregation itself is performed by the item_cmp_type() function. + The function also checks compatibility of row signatures for the + submitted items (see the spec for the cmp_row_type function). + + RETURN VALUES + 1 type incompatibility has been detected + 0 otherwise */ -static void agg_cmp_type(THD *thd, Item_result *type, Item **items, uint nitems) +static int agg_cmp_type(THD *thd, Item_result *type, Item **items, uint nitems) { uint i; type[0]= items[0]->result_type(); for (i= 1 ; i < nitems ; i++) + { type[0]= item_cmp_type(type[0], items[i]->result_type()); + /* + When aggregating types of two row expressions we have to check + that they have the same cardinality and that each component + of the first row expression has a compatible row signature with + the signature of the corresponding component of the second row + expression. + */ + if (type[0] == ROW_RESULT && cmp_row_type(items[0], items[i])) + return 1; // error found: invalid usage of rows + } + return 0; } @@ -1305,7 +1359,8 @@ void Item_func_between::fix_length_and_dec() */ if (!args[0] || !args[1] || !args[2]) return; - agg_cmp_type(thd, &cmp_type, args, 3); + if ( agg_cmp_type(thd, &cmp_type, args, 3)) + return; if (cmp_type == STRING_RESULT && agg_arg_charsets(cmp_collation, args, 3, MY_COLL_CMP_CONV, 1)) return; @@ -2021,7 +2076,8 @@ void Item_func_case::fix_length_and_dec() for (nagg= 0; nagg < ncases/2 ; nagg++) agg[nagg+1]= args[nagg*2]; nagg++; - agg_cmp_type(thd, &cmp_type, agg, nagg); + if (agg_cmp_type(thd, &cmp_type, agg, nagg)) + return; if ((cmp_type == STRING_RESULT) && agg_arg_charsets(cmp_collation, agg, nagg, MY_COLL_CMP_CONV, 1)) return; @@ -2710,7 +2766,8 @@ void Item_func_in::fix_length_and_dec() uint const_itm= 1; THD *thd= current_thd; - agg_cmp_type(thd, &cmp_type, args, arg_count); + if (agg_cmp_type(thd, &cmp_type, args, arg_count)) + return; if (cmp_type == STRING_RESULT && agg_arg_charsets(cmp_collation, args, arg_count, MY_COLL_CMP_CONV, 1)) diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index bccd4d4cafe..071acb57945 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -369,6 +369,8 @@ bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds) { Item *fake_conds= 0; SELECT_LEX *select_lex= &thd->lex->select_lex; + const char *operation = thd->lex->sql_command == SQLCOM_TRUNCATE ? + "TRUNCATE" : "DELETE"; DBUG_ENTER("mysql_prepare_delete"); List all_fields; @@ -383,14 +385,14 @@ bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds) DBUG_RETURN(TRUE); if (!table_list->updatable || check_key_in_view(thd, table_list)) { - my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "DELETE"); + my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, operation); DBUG_RETURN(TRUE); } { TABLE_LIST *duplicate; if ((duplicate= unique_table(thd, table_list, table_list->next_global, 0))) { - update_non_unique_table_error(table_list, "DELETE", duplicate); + update_non_unique_table_error(table_list, operation, duplicate); DBUG_RETURN(TRUE); } } @@ -895,7 +897,8 @@ bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok) if (!dont_send_ok) { db_type table_type; - mysql_frm_type(thd, path, &table_type); + if (mysql_frm_type(thd, path, &table_type) == FRMTYPE_VIEW) + goto trunc_by_del; if (table_type == DB_TYPE_UNKNOWN) { my_error(ER_NO_SUCH_TABLE, MYF(0), diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 3be844b6761..4be0aca3ea7 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1834,6 +1834,7 @@ bool st_lex::can_use_merged() case SQLCOM_UPDATE_MULTI: case SQLCOM_DELETE: case SQLCOM_DELETE_MULTI: + case SQLCOM_TRUNCATE: case SQLCOM_INSERT: case SQLCOM_INSERT_SELECT: case SQLCOM_REPLACE: diff --git a/sql/sql_select.cc b/sql/sql_select.cc index d65ecb6fa3b..dc018dd43bb 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -278,15 +278,30 @@ bool handle_select(THD *thd, LEX *lex, select_result *result, ref_pointer_array Array of references to Items used in current select DESCRIPTION - The function fixes fields referenced from inner selects and - also fixes references (Item_ref objects) to these fields. Each field - is fixed as a usual hidden field of the current select - it is added - to the all_fields list and the pointer to it is saved in the - ref_pointer_array if latter is provided. - After the field has been fixed we proceed with fixing references - (Item_ref objects) to this field from inner subqueries. If the - ref_pointer_array is provided then Item_ref objects is set to - reference element in that array with the pointer to the field. + The function serves 3 purposes - adds fields referenced from inner + selects to the current select list, resolves which class to use + to access referenced item (Item_ref of Item_direct_ref) and fixes + references (Item_ref objects) to these fields. + + If a field isn't already in the select list and the ref_pointer_array + is provided then it is added to the all_fields list and the pointer to + it is saved in the ref_pointer_array. + + The class to access the outer field is determined by the following rules: + 1. If the outer field isn't used under an aggregate function + then the Item_ref class should be used. + 2. If the outer field is used under an aggregate function and this + function is aggregated in the select where the outer field was + resolved or in some more inner select then the Item_direct_ref + class should be used. + The resolution is done here and not at the fix_fields() stage as + it can be done only after sum functions are fixed and pulled up to + selects where they are have to be aggregated. + When the class is chosen it substitutes the original field in the + Item_outer_ref object. + + After this we proceed with fixing references (Item_outer_ref objects) to + this field from inner subqueries. RETURN TRUE an error occured @@ -299,33 +314,64 @@ fix_inner_refs(THD *thd, List &all_fields, SELECT_LEX *select, { Item_outer_ref *ref; bool res= FALSE; + bool direct_ref= FALSE; + List_iterator ref_it(select->inner_refs_list); while ((ref= ref_it++)) { - Item_field *item= ref->outer_field; + Item *item= ref->outer_ref; + Item **item_ref= ref->ref; + Item_ref *new_ref; /* TODO: this field item already might be present in the select list. In this case instead of adding new field item we could use an existing one. The change will lead to less operations for copying fields, smaller temporary tables and less data passed through filesort. */ - if (ref_pointer_array) + if (ref_pointer_array && !ref->found_in_select_list) { int el= all_fields.elements; - ref_pointer_array[el]= (Item*)item; + ref_pointer_array[el]= item; /* Add the field item to the select list of the current select. */ - all_fields.push_front((Item*)item); + all_fields.push_front(item); /* If it's needed reset each Item_ref item that refers this field with a new reference taken from ref_pointer_array. */ - ref->ref= ref_pointer_array + el; + item_ref= ref_pointer_array + el; } - if (!ref->fixed && ref->fix_fields(thd, 0)) + + if (ref->in_sum_func) { - res= TRUE; - break; + Item_sum *sum_func; + if (ref->in_sum_func->nest_level > select->nest_level) + direct_ref= TRUE; + else + { + for (sum_func= ref->in_sum_func; sum_func && + sum_func->aggr_level >= select->nest_level; + sum_func= sum_func->in_sum_func) + { + if (sum_func->aggr_level == select->nest_level) + { + direct_ref= TRUE; + break; + } + } + } } + new_ref= direct_ref ? + new Item_direct_ref(ref->context, item_ref, ref->field_name, + ref->table_name, ref->alias_name_used) : + new Item_ref(ref->context, item_ref, ref->field_name, + ref->table_name, ref->alias_name_used); + if (!new_ref) + return TRUE; + ref->outer_ref= new_ref; + ref->ref= &ref->outer_ref; + + if (!ref->fixed && ref->fix_fields(thd, 0)) + return TRUE; thd->used_tables|= item->used_tables(); } return res; @@ -478,10 +524,6 @@ JOIN::prepare(Item ***rref_pointer_array, if (having && having->with_sum_func) having->split_sum_func2(thd, ref_pointer_array, all_fields, &having, TRUE); - if (select_lex->inner_refs_list.elements && - fix_inner_refs(thd, all_fields, select_lex, ref_pointer_array)) - DBUG_RETURN(-1); - if (select_lex->inner_sum_func_list) { Item_sum *end=select_lex->inner_sum_func_list; @@ -494,6 +536,10 @@ JOIN::prepare(Item ***rref_pointer_array, } while (item_sum != end); } + if (select_lex->inner_refs_list.elements && + fix_inner_refs(thd, all_fields, select_lex, ref_pointer_array)) + DBUG_RETURN(-1); + if (setup_ftfuncs(select_lex)) /* should be after having->fix_fields */ DBUG_RETURN(-1); @@ -5214,7 +5260,9 @@ get_store_key(THD *thd, KEYUSE *keyuse, table_map used_tables, } else if (keyuse->val->type() == Item::FIELD_ITEM || (keyuse->val->type() == Item::REF_ITEM && - ((Item_ref*)keyuse->val)->ref_type() == Item_ref::OUTER_REF) ) + ((Item_ref*)keyuse->val)->ref_type() == Item_ref::OUTER_REF && + (*(Item_ref**)((Item_ref*)keyuse->val)->ref)->ref_type() == + Item_ref::DIRECT_REF) ) return new store_key_field(thd, key_part->field, key_buff + maybe_null, @@ -13539,9 +13587,7 @@ create_distinct_group(THD *thd, Item **ref_pointer_array, ORDER *ord_iter; for (ord_iter= group; ord_iter; ord_iter= ord_iter->next) if ((*ord_iter->item)->eq(item, 1)) - break; - if (ord_iter) - continue; + goto next_item; ORDER *ord=(ORDER*) thd->calloc(sizeof(ORDER)); if (!ord) @@ -13556,6 +13602,7 @@ create_distinct_group(THD *thd, Item **ref_pointer_array, *prev=ord; prev= &ord->next; } +next_item: ref_pointer_array++; } *prev=0; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 6836811e7f3..6f953349c03 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -414,10 +414,11 @@ static int sort_keys(KEY *a, KEY *b) which has some duplicates on its right RETURN VALUES - void + 0 ok + 1 Error */ -void check_duplicates_in_interval(const char *set_or_name, +bool check_duplicates_in_interval(const char *set_or_name, const char *name, TYPELIB *typelib, CHARSET_INFO *cs, unsigned int *dup_val_count) { @@ -433,6 +434,13 @@ void check_duplicates_in_interval(const char *set_or_name, tmp.count--; if (find_type2(&tmp, (const char*)*cur_value, *cur_length, cs)) { + if ((current_thd->variables.sql_mode & + (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES))) + { + my_error(ER_DUPLICATED_VALUE_IN_TYPE, MYF(0), + name,*cur_value,set_or_name); + return 1; + } push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_NOTE, ER_DUPLICATED_VALUE_IN_TYPE, ER(ER_DUPLICATED_VALUE_IN_TYPE), @@ -440,6 +448,7 @@ void check_duplicates_in_interval(const char *set_or_name, (*dup_val_count)++; } } + return 0; } @@ -575,9 +584,10 @@ int prepare_create_field(create_field *sql_field, if (sql_field->charset->state & MY_CS_BINSORT) sql_field->pack_flag|=FIELDFLAG_BINARY; sql_field->unireg_check=Field::INTERVAL_FIELD; - check_duplicates_in_interval("ENUM",sql_field->field_name, - sql_field->interval, - sql_field->charset, &dup_val_count); + if (check_duplicates_in_interval("ENUM",sql_field->field_name, + sql_field->interval, + sql_field->charset, &dup_val_count)) + DBUG_RETURN(1); break; case FIELD_TYPE_SET: sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) | @@ -585,9 +595,10 @@ int prepare_create_field(create_field *sql_field, if (sql_field->charset->state & MY_CS_BINSORT) sql_field->pack_flag|=FIELDFLAG_BINARY; sql_field->unireg_check=Field::BIT_FIELD; - check_duplicates_in_interval("SET",sql_field->field_name, - sql_field->interval, - sql_field->charset, &dup_val_count); + if (check_duplicates_in_interval("SET",sql_field->field_name, + sql_field->interval, + sql_field->charset, &dup_val_count)) + DBUG_RETURN(1); /* Check that count of unique members is not more then 64 */ if (sql_field->interval->count - dup_val_count > sizeof(longlong)*8) { diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 1ec724a6338..7fb75732012 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -743,6 +743,7 @@ bool st_select_lex::cleanup() error= (bool) ((uint) error | (uint) lex_unit->cleanup()); } non_agg_fields.empty(); + inner_refs_list.empty(); DBUG_RETURN(error); }